Click doesn’t work after AJAX load – jQuery

If you use AJAX on your website, beware that events like click, submit, hover might not work if you don’t attach them properly. I will be using click event to describe the problem, but all of this applies to most events in jQuery.

Example data

Let say I have some kind of list that is divided into categories. You can select which category is visible and items are loaded via ajax.  Each item have hidden description that is shown on click. Like that:

When I load my page everything works fine until i change my category. Ajax still works fine but toggle for item description doesn’t work anymore. WAT?

Online example – example data

Solution 1

Click event is attachted to existing elements on page load. The key word here is “existing”. When we load something with ajax we manipulate DOM. We are placing totally new element. So what we need to do is to attach that event after placing new content. If you use .load() function (like in my example) you just need to place $(‘.toggle-item’).click() in the callback function:

that way, we are attaching click event to newly added elements.

We could of course move $(‘.toggle-item’).click() to the outside function to not repeat ourselves (for better maintenance and all, you know, right? DRY?).

If you use .ajax() function instead of .load() just attach event in .done() part (success hook) of ajax call.

solution 1 – check it

Solution 2

What if we don’t want to attach event everytime ajax is called. Is there any other, more “global” solution? Of course there is. We can use .on() function. Yay!

But wait!

Isn’t .click() same as .on(‘click’)? Yes it is. But here’s a fun part – we can delegate event.

Delegated events have the advantage that they can process events from descendant elements that are added to the document at a later time

So instead of attaching click event on completed ajax we just attaching it more errm “globally”:

We could attach it to $(‘body’).on(‘click’,’.toggle-item’,function(){}); but:

For best performance, attach delegated events at a document location as close as possible to the target elements. Avoid excessive use of document or document.body for delegated events on large documents.

solution 2 – check it

Remember – delegated event must be attached to the element that exist on the page at the time your code makes the call and doesn’t change during ajax calls – some kind of wrapper. This is the reason why people are attaching it to body, but if it’s possible select the element that is closer to targeted element.

On a side note in the earlier versions of jQuery instead of .on() we used .live() or .delegate() functions.

  • Share it on Twitter
  • Share it on Facebook
  • Share it on Pinterest
  • Share it on Google+
  • Share it on LinkedIn

Comments (29)Add comment

Take part in the discussion

Use pastebin.com or jsfiddle.net to add your code snippets
Your email address will not be published.