mpdc
mpdc

Reputation: 3560

Cloning form inputs with jQuery

There are numerous similar questions to mine, but none that address the specifics, unfortunately.

I have multiple forms on a page, all with the same structure:

<form>
    <div class="form-group">
        <select></select>
    </div>
    <div class="blank-container">
        <div class="form-group blank-group">
            <select></select>
        </div>
    </div>
    <button type="button" class="add-blank"></button>
    <button type="submit"></button>
</form>

The initial .form-group within each form has a pre-populated select, but the select within .blank-group is empty. When the .add-blank button is pressed, I want to clone() the last .blank-group and append it to the .blank-container.

I've managed this before using ids on a single form with the following code:

$("#add-blank").click(function() {
    $(".blank-group").last().clone().appendTo("#blank-container");
});

But now I have numerous forms on the same page with the same structure, I need to work with a specific .blank-container and I'm having troubles. This is what I have tried:

$(".add-blank").click(function() {
    blankGroup = $(this).closest("form").find(".blank-container").find(".blank-group").last();
    blankContainer = $(this).closest("form").find(".blank-container");
    blankGroup.clone().appendTo(blankContainer);
});

Upvotes: 1

Views: 74

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1074335

Use event delegation and traversal. Event delegation for the button press, and traversal to find things relative to the button:

$("selector-for-the-overall-container").on("click", ".add-blank", function() {
    var form = $(this).closest('form');
    form.find(".blank-group").last().clone().appendTo(form.find(".blank-container"));
});

$("selector-for-the-overall-container") could be $(document), but usually there's an element that's a bit closer to the things you want to capture the event on.

Live Example:

$("#container").on("click", ".add-blank", function() {
  var form = $(this).closest('form');
  form.find(".blank-group").last().clone().appendTo(form.find(".blank-container"));
});
<div id="container">
  <form>
    <div class="form-group">
      <select></select>
    </div>
    <div class="blank-container">
      <div class="form-group blank-group">
        This is the "blank" group
        <select></select>
      </div>
    </div>
    <button type="button" class="add-blank">Add</button>
    <button type="submit"></button>
  </form>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

I should say you don't need event delegation if all of those buttons will already exist when your code runs. If that's the case, you could do this:

$(".add-blank").click(function() {
    var form = $(this).closest('form');
    form.find(".blank-group").last().clone().appendTo(form.find(".blank-container"));
});

...but it sounded like things were fairly dynamic, so that's why I went for delegation.

Upvotes: 2

Related Questions