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.
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.
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.
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.
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…
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: