0

UPDATED: I include this codepen becuase I'm having issue with snippet https://codepen.io/ddcreate/pen/RJqOxo

I made this layout using bootstrap 4

current layout

What I want to achieve is when click on the "add new item", a new empty row will insert below. Since the site needs to be responsive, it's not possible to put all labels in a row and the fields in another row, otherwise the page will be messed up on smaller screen.

I found some posts about how to clond and insert using jQuery, I tried them but my issue is still here.

I hard code some script, not elegant, and they are not doing exactly what I want. The layout is messed up.

messed up layout

here is the code:

//add empty item fields
let addRow = $('.add-item');
//when click add fields
addRow.on('click', function() {
  let newRow = $('.need-to-dup').clone(),
    target = $('.need-to-dup').parent();
  target[0].append(newRow[0]);
  target[1].append(newRow[1]);
  target[2].append(newRow[2]);
  target[3].append(newRow[3]);
  //console.log(newRow, newRow[3])
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="item-form">
  <div class="row">
    <div class="col-lg-2 col-md-6">
      <label for="quanty">Quanty</label>
      <input class="need-to-dup" type="text" name="quanty" value="">
    </div>
    <div class="col-lg-4 col-md-6">
      <label for="item">Item</label>
      <input class="need-to-dup" type="text" name="item" value="">
    </div>

    <div class="col-lg-4 col-md-6">
      <label for="comment">Comment</label>
      <input class="need-to-dup" type="text" name="comment">
    </div>
    <div class="col-lg-2 col-md-6">
      <label for="remove">Remove</label>
      <button class="need-to-dup remove-item-button btn-block btn-outline-secondary" type="button" name="remove">
                  <i class="fa fa-trash-o" aria-hidden="true"></i>
                </button>
    </div>
  </div>
  <div class="add-item">
    <p>Add Another Item</p>
  </div>
</section>
Erik Philips
  • 53,428
  • 11
  • 128
  • 150
kukumalu
  • 233
  • 1
  • 2
  • 14
  • What is your expected result? – bcr666 Jun 28 '18 at 19:37
  • `target` contains a single element. But if you removed the indexes, you'd be placing a copy each field (`.need-to-dup`) inside the first column (first `.need-to-dup`'s parent). Wouldn't it make more sense to duplicate the entire row and insert it it just before the `add-item` div? – Gabriel Jun 28 '18 at 19:37
  • Provide CSS too. – Alex Jun 28 '18 at 19:40
  • Here's the codepen with CSS. https://codepen.io/ddcreate/pen/RJqOxo – kukumalu Jun 28 '18 at 20:16

4 Answers4

0

It's hard to tell what you want to do. Your "messed up" display looks good to me, and is how I would make mine look. If you are trying to duplicate the entire row though (labels and all):

addRow.on('click', function() {
  let newRow = $('.row')[0].clone();
  newRow.appendTo($('.item-form')[0]);
});
bcr666
  • 2,157
  • 1
  • 12
  • 23
0

Instead of duplicating each item, duplicate the whole row at once.

//add empty item fields
let addRow = $('.add-item');
//when click add fields
addRow.on('click', function() {
  let lastRow = $('.row').last()
  lastRow.after(lastRow.clone());
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="item-form">
  <div class="row">
    <div class="col-lg-2 col-md-6">
      <label for="quanty">Quanty</label>
      <input class="need-to-dup" type="text" name="quanty" value="">
    </div>
    <div class="col-lg-4 col-md-6">
      <label for="item">Item</label>
      <input class="need-to-dup" type="text" name="item" value="">
    </div>

    <div class="col-lg-4 col-md-6">
      <label for="comment">Comment</label>
      <input class="need-to-dup" type="text" name="comment">
    </div>
    <div class="col-lg-2 col-md-6">
      <label for="remove">Remove</label>
      <button class="need-to-dup remove-item-button btn-block btn-outline-secondary" type="button" name="remove">
        <i class="fa fa-trash-o" aria-hidden="true"></i>
      </button>
    </div>
  </div>
  <div class="add-item">
    <p>Add Another Item</p>
  </div>
</section>
Barmar
  • 741,623
  • 53
  • 500
  • 612
0

Here is my solution:

  • Clone the .row element using .clone()
  • Use .find() to find any labels and remove them from the clone
  • .append() that clone into the .item-form element.

//add empty item fields
let addRow = $('.add-item');
//when click add fields
let original = $('.row');

addRow.on('click', function() {
  let clone = $(original).clone();
  $(clone).find('label').remove();
  $('.item-form').append(clone);
})
body {
  font-family: 'Quicksand', sans-serif;
}

nav {
  background: #66a6ff;
  background-image: linear-gradient(120deg, #66a6ff 0%, #89f7fe 100%);
  line-height: 70px;
  color: #fff;
  font-size: 24px;
  font-weight: 700;
  box-shadow: 0px 0px 51px 0px rgba(0, 0, 0, 0.08), 0px 6px 18px 0px rgba(0, 0, 0, 0.05)
}

button, .add-item {
  transition: all .2s ease-in-out;
}
/* ***
        Customer & Delivery Info Styling
*** */

input, .select-driver {
  width: 100%;
  margin-bottom: .5rem;
  height: 40px;
}

.form-control {
  border-color: #a9a9a9;
}

fieldset {
  background-color: white;
  border: 1px solid #e9ecef;
  border-radius: 10px;
  padding: 5px 20px 18px;
  margin: 20px auto;
  box-shadow: 0 6px 15px rgba(36,37,38,0.08);
}

legend {
  font-size: 18px;
  width: auto;
  padding: 0 15px;
  text-align: center;
}

#recurring-checkbox {
  position: relative;
  top: -8px;
}

input[type=checkbox] {
    display: inline-block;
    margin-bottom: 0;
    width: 30px;
    height: 30px;
    background-repeat: no-repeat;
    background-position: center center;
    background-size: contain;
    -webkit-appearance: none;
    outline: 0;
    border: none;
}

input[type=checkbox]:checked {
    background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" x="0px" y="0px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve"><path id="checkbox-3-icon" fill="#FD6585" d="M81,81v350h350V81H81z M227.383,345.013l-81.476-81.498l34.69-34.697l46.783,46.794l108.007-108.005 l34.706,34.684L227.383,345.013z"/></svg>');
}

input[type=checkbox]:not(:checked) {
    background-image: url('data:image/svg+xml;utf8,<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve"> <path id="checkbox-9-icon" fill="#f68ba2" d="M391,121v270H121V121H391z M431,81H81v350h350V81z"></path> </svg>');
}

/* ***
        Items Detail Styling
*** */

.add-item {
  border: 3px dashed;
  font-size: 16px;
  color: #C3C3C3;
  text-align: center;
  margin: 20px 0;
}

.add-item p {
  margin: 0 auto;
  line-height: 40px;
}

.add-item:hover {
  color: #989898;
  background-color: rgba(215, 214, 214, 0.56);
  cursor: pointer;
}


/* ***
        Notes and Buttons Styling
*** */

textarea {
  height: auto;
  width: 100%;
  margin-bottom: 0;
}

.save-button {
  border: 1px solid;
  border-radius: 5px;
  font-size: 18px;
  font-weight: 500;
  line-height: 40px;
  box-shadow: 0 6px 15px rgba(36,37,38,0.08);
  margin: 20px auto;
}

.save-button:hover {
  background-color: #66a6ff;
  border-color: #66a6ff;
}

.remove-item-button {
  color: #f68ba2;
  border: 1px solid #a9a9a9;
  border-radius: 5px;
  height: 40px;
}

.remove-item-button:hover {
  color: #eee;
  background-color: #f68ba2;
  border-color: #fff;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js"></script>
<link href="http://maxcdn.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.css" rel="stylesheet"/>
<section class="item-form">
  <div class="row">
    <div class="col-lg-2 col-md-6">
      <label for="quanty">Quanty</label>
      <input class="need-to-dup" type="text" name="quanty" value="">
    </div>
    <div class="col-lg-4 col-md-6">
      <label for="item">Item</label>
      <input class="need-to-dup" type="text" name="item" value="">
    </div>

    <div class="col-lg-4 col-md-6">
      <label for="comment">Comment</label>
      <input class="need-to-dup" type="text" name="comment">
    </div>
    <div class="col-lg-2 col-md-6">
      <label for="remove">Remove</label>
      <button class="need-to-dup remove-item-button btn-block btn-outline-secondary" type="button" name="remove">
              <i class="fa fa-trash-o" aria-hidden="true"></i>
            </button>
    </div>
  </div>
</section>

<div class="add-item">
  <p>Add Another Item</p>
</div>
Alex
  • 2,164
  • 1
  • 9
  • 27
  • Hey @Alex, I made a codepen which has css. I have issue putting css here. https://codepen.io/ddcreate/pen/RJqOxo – kukumalu Jun 28 '18 at 20:13
  • @kukumalu added CSS, you can fix the label padding without labels in your own time :) – Alex Jun 28 '18 at 20:23
  • I changed the `let original` to `let original = $('.item-form').find('.row');` because there are other elements using the className `row`. However after I made this change, new row is added below the `
    ` :(
    – kukumalu Jun 28 '18 at 21:04
  • I changed it to `clone.insertBefore($(this))` and the new row is added above the `
    ` now
    – kukumalu Jun 28 '18 at 21:35
0

I think the best solution for you is:

  1. Clone div.row
  2. Change name attribute with an index (it could be quite problematic)
  3. Remove label from the clone's element

I did this easy example:

$(document).ready(function(){

 $(".add-item").on("click", function() {
   var rows = $(".row","section.item-form"),
      first = rows.first(), last = rows.last(), clone = first.clone();
        console.log(first);
    clone.insertAfter(last).find("[name!=''][name]").each(function() {
     var name = $(this).attr("name").split("-")[0];
     $(this).siblings("label").remove();
     $(this).attr("name", name + "-" + rows.length);
    });
    
  });

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<section class="item-form">
         <div class="row">
          <div class="col-lg-2 col-md-6">
            <label for="quanty-0">Quanty</label>
            <input class="need-to-dup" type="text" name="quanty-0" value="" >
          </div>
          <div class="col-lg-4 col-md-6">
            <label for="item-0">Item</label>
            <input class="need-to-dup" type="text" name="item-0" value="" >
          </div>

          <div class="col-lg-4 col-md-6">
            <label for="comment-0">Comment</label>
            <input class="need-to-dup" type="text" name="comment-0">
          </div>
          <div class="col-lg-2 col-md-6">
            <label for="remove-0">Remove</label>
            <button class="need-to-dup remove-item-button btn-block btn-outline-secondary" type="button" name="remove-0">
              <i class="fa fa-trash-o" aria-hidden="true"></i>
            </button>
          </div>
      </div>
      <div class="add-item">
        <p>Add Another Item</p>
      </div>
    </section>

Or you can watch it in this fiddle

**.find("[name!=''][name]")** : attr *name* must exist and has to have some value
.siblings : jquery description [here][2]
.clone : jquery description [here][2]

Hope it will help.

Loris
  • 101
  • 7
  • Hi Loris, I can't include the label names. each new row needs to be empty without labels. – kukumalu Jun 28 '18 at 20:11
  • Sorry, was my bad i forgot aobut that during the coding. I edited the script. Thank you! – Loris Jun 28 '18 at 20:16
  • Hi Loris, thank you for the solution. I have another question...so now when I type inside the input field, and then duplicate, the new row contains content. How can I make empty new row even the previous row has content? – kukumalu Jun 28 '18 at 20:45
  • Just add a _.val("")_ when you change _name_ attribute. Like this: `$(this).attr("name", name + "-" + rows.length).val("")` – Loris Jun 28 '18 at 21:01
  • what's the difference between $(element) and (element) ? – kukumalu Jun 28 '18 at 21:41
  • I think you can easily find the difference surfing the internet. Anyway this is one stackoverflow [link](https://stackoverflow.com/questions/1150381/what-is-the-meaning-of-sign-in-javascript) – Loris Jun 28 '18 at 21:52