How to Use jQuery on() for Event Delegation
Event delegation in jQuery allows you to attach a single event
listener to a parent element that responds to events triggered by its
current or future child elements. This article explains how event
delegation works with the jQuery on() method, breaks down
the required syntax, and demonstrates practical examples to handle
dynamically created DOM elements efficiently.
Understanding Event Delegation
In standard event handling, you attach a listener directly to a specific DOM element. However, this approach fails when new elements are inserted into the page dynamically via JavaScript or AJAX, because the listener was only bound to elements existing at the time of code execution.
Event delegation solves this problem by taking advantage of event bubbling. When an event occurs on a child element, it bubbles up the DOM tree to its parent elements. By placing a listener on a static ancestor element, you can intercept the event as it bubbles up and execute a handler function specifically for the targeted child.
The .on() Delegation
Syntax
To configure the on() method for event delegation, you
pass a selector for the target child elements as the second
argument:
$(parentSelector).on(eventType, childSelector, handlerFunction);parentSelector: A static container element that is already present in the DOM when the script runs (e.g.,document,body, or a specific wrapperdiv).eventType: The event to listen for (such as'click','submit', or'mouseover').childSelector: A string containing a selector expression to filter the descendant elements that trigger the event.handlerFunction: The function to execute when the event triggers on the child element.
Direct vs. Delegated Event Handlers
Direct Event Binding (Non-Delegated)
// Only attaches to buttons present in the DOM on initial load
$('button.delete-btn').on('click', function() {
$(this).closest('li').remove();
});If a new button.delete-btn is added to the page later,
clicking it will do nothing because the event listener was never bound
to it.
Delegated Event Binding
// Attaches to the static list container, handling clicks for all current and future buttons
$('#todo-list').on('click', 'button.delete-btn', function() {
$(this).closest('li').remove();
});Within the handler function, this refers to the specific
child element (button.delete-btn) that triggered the event,
not the parent container (#todo-list).
Practical Example: Handling Dynamic Elements
Below is a complete implementation showing how event delegation allows dynamically added list items to inherit click actions automatically:
<ul id="item-list">
<li>Item 1 <button class="remove">Delete</button></li>
<li>Item 2 <button class="remove">Delete</button></li>
</ul>
<button id="add-item">Add New Item</button>
<script>
$(document).ready(function() {
// Event delegation on the parent <ul> container
$('#item-list').on('click', '.remove', function() {
$(this).parent('li').remove();
});
// Code to dynamically add new items
$('#add-item').on('click', function() {
$('#item-list').append('<li>New Item <button class="remove">Delete</button></li>');
});
});
</script>When a user clicks "Add New Item", the newly created list item's delete button automatically triggers the delegated removal logic without requiring any additional event binding.
Best Practices
- Bind to the Closest Static Parent: Avoid binding
delegated events to
$(document)or$('body')unless necessary. Attaching events to the closest non-dynamic ancestor improves performance by minimizing the distance the event needs to bubble. - Conserve Memory: Using a single delegated handler for dozens or hundreds of child elements (like table rows or list items) uses significantly less browser memory than attaching distinct event handlers to every single element.