0

I have a table that I've created dynamically and in each row there is a button that will clear that row. The button works fine in the first row, but doesn't do anything in the following rows. To troubleshoot this, I set the button to give me an alert on click, but only the first button is registering.

I've changed the button to be an ID and a Class, but that doesn't seem to do anything either.

Here is the code:

 //dynamically create 4 rows
 $(document).ready(function(){
 var rowsAdd = $('#addTable tbody >tr');
 var rA = rowsAdd.length;
 while (rA<5) {
  $('#addTable tbody>tr:last').clone().insertAfter('#addTable tbody>tr:last');
  rA++;
 }
})

 //alert on button click
 $('.clear').each(function(index){
  $(this).on("click",function(){
  alert("Button " +index+ " is clicked");
 });
 });
  
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="addTable">
        <tbody>
          <tr>
            <th style="width: 10%">Class #</th>
            <th style="width: 30%;">Course Title</th>
            <th style="width: 20%;">Catalog Number</th>

   <th></th>
          </tr>
   
   <div class="addTable">
          <tr>
   <td class="classNumID"></td>
   <td>
   <input list="courses" name="courseInput" placeholder="Course" class="courseClass" oninput="UpdateCatNumbers()">
      <datalist id="courses" name="courseDatalist">
     <!--Filled in script-->     
      </datalist>
   </td>
          <td>
    <input list="catalogs" name="catalogInput" placeholder="Catalog Number" id="catalogID" class="catClass" oninput="UpdateCourseNames()">
      <datalist id="catalogs" name="catalogDatalist">
     <!--Filled in script-->
      </datalist>
      </td>
   <td><button class="clear">−</button></td>
          </tr>
    </div>    
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Doodlebug
  • 21
  • 8
  • Also: https://stackoverflow.com/questions/9454645/does-id-have-to-be-unique-in-the-whole-page – Taplar Jul 11 '18 at 20:39
  • I did take a look at that thread, but I have tried everything in the suggestions and they are still not working for me. – Doodlebug Jul 11 '18 at 20:40
  • Then you did not implement the delegate event listeners properly. This is still a duplicate question. – Taplar Jul 11 '18 at 20:41
  • Move your `$('.clear').each() etc.` inside of your `document.ready()` after you append the dynamic rows. – Ryan Wilson Jul 11 '18 at 20:41
  • Also related: http://learn.jquery.com/events/event-delegation/ – Taplar Jul 11 '18 at 20:43
  • Excellent @RyanWilson! Thanks so much! – Doodlebug Jul 11 '18 at 20:44
  • @Doodlebug You're welcome. Have a good day. Remember that events can only be attached once the element(s) exist in the DOM, so if you ever append new elements dynamically, you'll need to add the events after they exist, as other's have pointed out. – Ryan Wilson Jul 11 '18 at 20:45
  • @RyanWilson that answer completely ignores the existance of delegate event handlers which are made for this very situation. Creating a delegate event handler on the pre-existing parent element that the dynamic elements are created into, allows you to create one single binding that will capture and process the events from future children. It is not a requirement to directly bind on the dynamic elements. – Taplar Jul 11 '18 at 20:54
  • @Taplar Good point. Thanks for pointing that out. Doodlebug, you will want to look into what Taplar suggested in his post. – Ryan Wilson Jul 11 '18 at 23:54

1 Answers1

3

As mentioned in the duplicate post, you can use a delegate event binding to bind on the parent element that exist on page load, that will listen for the events from future children and handle them when it happens.

$('#addTable').on('click', '.clear', function(e){
  alert('button clicked', this);
});

The elements are added to the addTable which exists on page load. When a click event happens on any of the (future) children with the class of 'clear', that click event will bubble up to the parent. The parent will check to see if the event originated from a child that matches that selector ('.clear') and when it does, it will process the event against the child as if it had been directly bound to it.

Taplar
  • 24,788
  • 4
  • 22
  • 35