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:

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:

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:

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:

One last thing…

If you liked this article, I'd be incredibly grateful if you tweeted about it.

Also, I don't send emails often but when I do, I try to fill them full of useful goodies. If you like code snippets & dev tips, join my mailing list. There's no catch but I'll probably want to tell you about any new plugins & tools I build.