How jQuery event handlers can survive AJAX refresh using event delegation

How many time you were working hard to add smart AJAX (or similar) refresh function to your complex user interface just to find out that your jQuery event handlers are not working anymore after the refresh? That is, as you your original DOM elements are gone, event handlers assigned to them are gone too. That’s so much frustrating, when you almost get it working, you realize that you have to rewrite most of your shiny JS code in order to stay working after AJAX refresh.

I used to implement clumsy workarounds by supplying event handlers initialization code with HTML returned by AJAX. But that code is run by jQuery using eval() function making it impossible to debug. So I switched to encapsulating event handlers into a function that could be called after each refresh. But once again, I need to rewrite my code so that event handlers are assigned to the elements of refreshed container, otherwise I end up assigning event handlers to elements that already have them.

That was much pain resulting in dirty code until I found out jQuery (and JS) already have a solution to this problem via delegation of events. In easy words: you can assign event handlers to static elements that are not refreshed but contain refreshed elements. You just have to add a selector specifying child elements you want the event to be handled for. If you have no idea, you can assign event handlers to body element as it will always stay there.

So if you have a code like this:


$('.my-button').click(function() { 
    alert('My button is clicked'); 
});

…and you find out that the button is replaced by AJAX and stops working, you can simply rewrite it to the following syntax:


$('body').on('click', '.my-button', function() { 
    alert('My button is clicked'); 
});

And this event handler will still work after AJAX refresh!!!

Despite the handler is assigned to “body” element, the “this” variable passed to the event handler will still contain “.my-button” element, so no change to the event handler body is usually required.

Notice the code change is quite minimal, isn’t it? You just need to change the way event handler is assigned a bit, you can even automate that code rewrite with regular expressions. No more moving code to HTML returned by AJAX, no more “init” functions that restore event handlers, no tears: it just works.

At the moment I’m not aware of any drawbacks of this method. Maybe performance?

As I’m not really a big JS expert, I was afraid it could work for simple events like “click” but not work for more specific ones like “change”. So I wrote this simple example to verify if it works for “change” event: https://jsfiddle.net/ab49Lprq/. Yes, it works! I also tested focus event and it works toothanks to bubbling of JS events. I think only custom event handler that stops bubbling may prevent it form working as expected but still you can handle the even in an element inside the one that stops bubbling.

So have fun writing nice jQuery user interface automation and make sure it still works like a charm (but easy to debug just in case;) even if you heavily refresh parts of your screen with AJAX.

5 thoughts on “How jQuery event handlers can survive AJAX refresh using event delegation”

  1. No, it actuallyu works. Just before new Ajax call I’m removing #nextPage, and rendering it back with PHP. It didn’t work until I replaced:
    $(“#nextPage”).click(function() { … });
    with:
    $(‘body’).on(‘click’, ‘#nextPage’, function() { …});

    Reply

Leave a Comment