Delegate jQuery event handlers when working with dynamic content

If you’ve had the pleasure of loading up items dynamically (via AJAX) using jQuery, you may have come across issues where event handlers on dynamically loaded items seemingly cease to work on newly loaded items.

I’ve been there and I remember how frustrating it was when I first encountered it so I’m addressing this very scenario with some code examples for you to nick.

What’s the actual problem?

Typically, we’ll select our DOM elements and bind event handlers on document.ready and this is generally fine and dandy. If, however, we append new elements to the DOM, jQuery won’t go and bind any necessary event handlers for us. This means we need to bind the handlers to the newly added elements which, if we aren’t careful, we could end up binding the same handler multiple times to elements already in the DOM.

Event propagation + delegation as a clean fix

A cleaner way to play it is to leverage event propagation — that is, the event “bubbling up” through the DOM tree — and bind our handler to an element further up the DOM hierarchy. This basically allows us to bind a function to handle events that are fired on child, grandchild, great-grandchild (you get the idea) element.

Any generic click handler would catch any and all click events made to any element within the element the handler is bound to. (was that even English? I hope so.)

To ensure we only catch clicks on particular sub elements, we can use event delegation — something that jQuery makes very easy for us.

First, some markup to set the mood

Just so we have something to ‘visualise’, here is the markup our jQuery will be acting upon:

<div class="PostsGrid">
<!– This is our div containing our post items –>
<div class="PostsGrid__posts">
<a href="#" class="PostsGrid__post"><!– …Post grid item here… –></a>
<a href="#" class="PostsGrid__post"><!– …Post grid item here… –></a>
<a href="#" class="PostsGrid__post"><!– …Post grid item here… –></a>
</div>
<!– A button to load more posts –>
<button class="PostsGrid__more">Load More Posts</button>
</div>
view raw _markup.html hosted with ❤ by GitHub

It’s nothing fancy — just a container element with a posts grid inside it and a button to add more. The button isn’t used in the examples here, it’s just there for a bit of context.

A standard jQuery click event handler

The standard click handler could look as follows:

// Shorthand for $( document ).ready()
$(function () {
// Bind a callback to handle click events on all post grid items.
// This event handler is bound directly to each post grid item and
// will only work on items that were on the page when the handler
// was originally bound.
$('.PostsGrid__post').click(function (event) {
// Handle click event.
});
});

In the above code, on document.ready, an event handler is bound to every element in the document with the class name .PostsGrid__post. Easy.

This will work fantastically on posts that already exist in the DOM. However, if you go and append more posts, the above code won’t facilitate clicks on those posts. Enter delegation…

A delegated jQuery click event handler

Here’s the same example, just modified to leverage event delegation:

// Shorthand for $( document ).ready()
$(function () {
// Bind a callback to the element that houses all post grid items.
// This event handler is bound on an element further up the DOM tree
// and instructed to target elements with the .PostsGrid__post class.
// This approach will work on any items that are dynamically added to
// the DOM, provided they are within the .PostsGrid__posts element.
$('.PostsGrid__posts').on('click', '.PostsGrid__post', function (event) {
// Handle click event.
});
});

In this example, an event handler is bound to the posts container and jQuery is instructed to only fire the handler when a click event originated from an element with the class name `.PostsGrid__post`.

Using this approach will allow us to add and remove post items from the .PostsGrid__posts container and clicks on any and all of the post elements will trigger our event handler.

If you’d like to read more about event delegation in jQuery, check out the following:

Got a project? Let's talk.

From website design & SEO through to custom WordPress plugin development. I transform ideas into dynamic, engaging, and high-performing solutions.
Subscribe to get the latest insights & updates in the world of web and how it impacts your business and website.
© 2024 Phil Kurth  |  All rights reserved.