jQuery makes it pretty easy to bind to events for elements that are already present when the page loads. What if new elements are added after the page loads? How do you bind to dynamically added elements? Let’s learn how!
Table Example
Let’s say we have a table that has three columns:
- First Name
- Last Name
- Action
In the Action column, there will be a Remove button with a class called remove.
<table>
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr>
<td>Jesse</td>
<td>Pinkman</td>
<td><button type="button" class="remove">Remove</button></td>
</tr>
<tr>
<td>Saul</td>
<td>Goodman</td>
<td><button type="button" class="remove">Remove</button></td>
</tr>
<tr>
<td>Gus</td>
<td>Fring</td>
<td><button type="button" class="remove">Remove</button></td>
</tr>
</tbody>
</table>
Under the table, there will be an Add button with an id called add.
<button type="button" id="add">Add</button>
Bind To Existing Elements
Before we can do anything, we have to make sure the page has actually finished loading.
$(function() {
// Do stuff now that the page has finished loading
});
When the Remove button is clicked, we want to remove the respective row. First, we have to select all Remove buttons. We can do this by looking for the remove class we put on each button.
$('.remove')
Now let’s create an event listener and run a function called onRemove when the click event happens.
$(function() {
$('.remove').on('click', onRemove);
});
Take another look at where the button is in the DOM tree. It’s inside a <td> element, which is inside a <tr> element.
<tr>
<td>
<button type="button" class="remove">Remove</button>
</td>
</tr>
So if we wanted to remove the row (<tr>), we’d have to traverse up two elements in the DOM tree. jQuery makes this easy using the parent and remove methods.
Let’s create that onRemove function that will run when the click happens on any Remove button. The this keyword represents the respective button element that was clicked. If we wrap it in the jQuery selector, we’ll be able to use any of the jQuery methods. We want to move up two elements in the DOM tree, so let’s call parent twice and then call the remove method to remove the row!
function onRemove() {
$(this).parent().parent().remove();
}
Bind To Dynamically Added Elements
Remember that Add button under the table? We want to add a new row when it’s clicked. First, we have to select the Add button. We can do this by looking for the id of add we put on the button.
$('#add')
Now let’s create an event listener and run a function called onAdd when the click event happens.
$(function() {
$('#add').on('click', onAdd);
$('.remove').on('click', onRemove);
});
Let’s create that onAdd function that will run when the click happens on the Add button. We select the table and append a new row of html to it.
function onAdd() {
$('table').append('<tr><td>Walter</td><td>White</td><td><button type="button" class="remove">Remove</button></td></tr>');
}
If you try clicking on the Remove button on the newly added row nothing happens! That’s because we told jQuery to listen for click events on Remove buttons that were on the page already. We need to change that to listen for click events whether they were on the page already or added after the fact!
Let’s listen to the entire document for clicks on the remove class and run the onRemove function.
$(document).on('click', '.remove', onRemove);
Now try clicking on the Remove button on a newly added row. The row is successfully removed!
By the way, you don’t have to select the entire document. You can narrow the search down to a parent container, which would be more efficient. For example, maybe add an id to the table called list. Then select the list id instead of the whole document.
$('#list').on('click', '.remove', onRemove);
CodePen Example
Visit our website at https://nightwolf.dev and follow us on Twitter!
Top comments (3)
You haven't actually binded to the new elements at all, rather you are using event delegation to handle the events further up - via event bubbling/propagation. No binding changes
Handle events might have been better than saying bind. Thanks!
Thanks! This was an example if jQuery was in use.