mafortis
mafortis

Reputation: 7138

JavaScript event handler isn't called on appended button

I have form where I can add options and add new fields of options. I am using JQuery for this. The problem is that the remove button of added fields doesn't work.

Here's my form:

one

Logic

  1. I click Add New button and new row will add Working
  2. I click Remove it has to remove that row Not Working

$(function() {

  //add row for options
  $("#addnewoptinrow").click(function(e) {
    e.preventDefault();
    $('.newrow').append('<div class="row mt-3 newrowadded"><div class="col-md-8"><input name="options[]" type="text" class="form-control" placeholder="Option Name"></div><div class="col-md-2"><input name="optionsprices[]" type="number" class="form-control" placeholder="Price"></div><div class="col-md-2"><button type="button" class="removerow btn btn-danger" id="removerow">Remove</button></div></div>');
  });

  //Remove the row
  $('.removerow').on('click', function(e) {
    e.preventDefault();
    $('.newrowadded').closest("div.row").remove();
  });

});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="row">
  <div class="col-md-8">
    <input name="options[]" type="text" class="form-control" placeholder="Option Name">
  </div>
  <div class="col-md-2">
    <input name="optionsprices[]" type="number" class="form-control" placeholder="Price">
  </div>
  <div class="col-md-2">
    <button class="addnewqtydiscmsgsave btn btn-primary" id="addnewoptinrow">Add New</button>
  </div>
</div>
<div class="newrow"></div>

Any idea how to fix that remove action?

Upvotes: 1

Views: 115

Answers (5)

Aydin4ik
Aydin4ik

Reputation: 1935

The issue is that you are trying to bind actions on elements that are not yet created - you should use a more general binding as below:

$(function(){

    //add row for options
    $("#addnewoptinrow").click(function(e){
        e.preventDefault();
        $('.newrow').append('<div class="row mt-3 newrowadded"><div class="col-md-8"><input name="options[]" type="text" class="form-control" placeholder="Option Name"></div><div class="col-md-2"><input name="optionsprices[]" type="number" class="form-control" placeholder="Price"></div><div class="col-md-2"><button type="button" class="removerow btn btn-danger" class="removerow">Remove</button></div></div>');
    });

    //Remove the row
    $(document).on('click','.removerow', function(e){
        e.preventDefault();
        $(this).parent().parent().remove();
    });

});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div class="row">
    <div class="col-md-8">
        <input name="options[]" type="text" class="form-control" placeholder="Option Name">
    </div>
    <div class="col-md-2">
        <input name="optionsprices[]"  type="number" class="form-control" placeholder="Price">
    </div>
    <div class="col-md-2">
        <button class="addnewqtydiscmsgsave btn btn-primary" id="addnewoptinrow">Add New</button>
    </div>
</div>
<div class="newrow"></div>

Pay attention to the

$(document).on('click','.removerow', function(e){

line of code. This line appends the action to all of the '.removerow' elements, present and future. So when new elements are added with this class, they are automatically assigned this action (BTW, had to change your HTML from id="removerow" to class="removerow", to avoid duplicate ID's).

And please read this topic, it goes into more details of your issue.

Upvotes: 0

Pinke Helga
Pinke Helga

Reputation: 6702

In oder to match your event listener to later created elements, you need to delegate it. In older JQuery versions it was done by the .delegate method, however, in recent versions this method is deprecated. Now you can delegate by ancestorCollection.on('query-selector', 'event', listener).

In your example something like

$('.newrow').on('.removerow', 'click', function(e){ /*...*/ })

Upvotes: 0

Dacre Denny
Dacre Denny

Reputation: 30390

There are two issues in your code:

  • the call to on() is missing the "selector" argument, which means that no elements dynamically added in future will have the click event boundy
  • your remove logic needs to be executed relative to the button being clicked

Try the following changes in your .removerow click handler:

/* 
Bind the click handler to all elements dynamically added that match the
.removerow selector 
*/
$('body').on('click','.removerow', function(e){
    e.preventDefault();

    /* 
    Explaination:
    1. from "this" remove button being clicked, 
    2. select the closest ".newrowadded" and, 
    3. remove it 
    */
    $(this).closest(".newrowadded").remove();
});

See the snippet below for your a working example based off of your code:

$(function() {

  //add row for options
  $("#addnewoptinrow").click(function(e) {
    e.preventDefault();
    $('.newrow').append('<div class="row mt-3 newrowadded"><div class="col-md-8"><input name="options[]" type="text" class="form-control" placeholder="Option Name"></div><div class="col-md-2"><input name="optionsprices[]" type="number" class="form-control" placeholder="Price"></div><div class="col-md-2"><button type="button" class="removerow btn btn-danger">Remove</button></div></div>');
  });

  //Remove the row
  $('body').on('click', '.removerow', function(e) {
    e.preventDefault();
    $(this).closest(".newrowadded").remove();
  });

});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
<div class="row">
  <div class="col-md-8">
    <input name="options[]" type="text" class="form-control" placeholder="Option Name">
  </div>
  <div class="col-md-2">
    <input name="optionsprices[]" type="number" class="form-control" placeholder="Price">
  </div>
  <div class="col-md-2">
    <button class="addnewqtydiscmsgsave btn btn-primary" id="addnewoptinrow">Add New</button>
  </div>
</div>
<div class="newrow"></div>

Upvotes: 2

XuWang
XuWang

Reputation: 359

Button.removerow was added later. you can try this:

  //add row for options
  $("#addnewoptinrow").click(function(e) {
    e.preventDefault();
    $('.newrow').append('<div class="row mt-3 newrowadded"><div class="col-md-8"><input name="options[]" type="text" class="form-control" placeholder="Option Name"></div><div class="col-md-2"><input name="optionsprices[]" type="number" class="form-control" placeholder="Price"></div><div class="col-md-2"><button type="button" class="removerow btn btn-danger" id="removerow">Remove</button></div></div>');


    //Remove the row
    $('.removerow').on('click', function(e) {
      e.preventDefault();
      $('.newrowadded').closest("div.row").remove();
    });
  });



Upvotes: 0

David Fontes
David Fontes

Reputation: 1508

The problem is that your code is only being executed on page load and at this time, your remove button is not yet created. You need to add an event listener to the remove button after your remove button has been created.

Upvotes: 0

Related Questions