Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery automatically register event handler(s) to user actions on elements that are added to DOM by Ajax response

For ajax web application that has many screens and navigations, to attach event handlers for div or links or buttons, we can code like :

//Using $.on inside Ajax success handler

$("#container").on("click", "#selector", function(event){

});
  • This approach will NOT work if container doesn't exists in the DOM. To make it work, will have to use document or body as the container, the performance may not be good.

  • There could be many lines of code in Ajax success handler. To organize better, can move the code to a function and call that function in Ajax success handler. But we have to make many register event functions for all permutations and combinations.

  • Register functions code cluttering.

  • If event handler was already registered, registering again will cause two even handlers. So we have to un-register and register (OR attach only if not attached already) - Not sure about performance problem.

Any alternatives ?

I am thinking of following :

  • Maintain a map of container, target, and click event handler in one place for a module.
  • In ajaxComplete global event handler, if xhr.responseHTML has the container, attach event handler to target elements (attach only if not attached already).

    $(document).ajaxComplete(function(e, xhr, settings){
       for(ind in clickEventListeners){eventlistner = clickEventListeners[ind];
        if($(eventlistner.container,xhr.responseHTML).length > 0){
          $(eventlistner.target).on("click",function(){
          eventlistner.processor(this);
          });
      }
     }
    });
    

Pros : All event handlers documented in one place for a module. No code cluttering in for each ajax success handler.

Cons : I am not sure if any.

Please advise if any suggestions.

like image 591
Samba Avatar asked Sep 12 '12 06:09

Samba


2 Answers

Updated

Binding an event to an element that will be dynamically added requires placing the listener on the document, not the element as of version 1.9+. From Jquerys api you can find this line:

"Event handlers are bound only to the currently selected elements; they must exist on the page at the time your code makes the call to .on()."

Therefor binding the event to the document and placing the selector afterwards will allow this listener to actually be recognized.

$(document).delegate( "#selector", "click",

or

$(document).on( "click", "#selector",

Example: http://jsfiddle.net/2HA7d/

In previous Jquery releases the live() function could have been used which actually placed the listener to the document allowing this to function exactly as you would think:

$("#selector").live("click",

Example: http://jsfiddle.net/q3jYB/

The second example functions the same as the first example.

As the element does not exist yet, javascript is unable to add an event listener for the element you are looking for. So, when trying to add a listener for dynamically added elements and you are using a newer jquery version (1.9+) and using on() or delegate(), add your event listener to the document as seen in the first Fiddle provided.

Edit:

as Will I AM stated in the comments, adding the event listener to the container if possible is also a very viable option and may improve performance

Sources:

https://api.jquery.com/on/

http://jquery.com/upgrade-guide/1.9/

How does jQuery .live() work?

Hope this helps.

like image 133
Jesse Avatar answered Nov 09 '22 20:11

Jesse


I was in similar situation like you, try this, this works great on my end!

  • First in master file I bind event handler like this:

    $('body').bind( 'gridloaded', function(e,f) { my logic } );

  • In ajax files that are dynamically populating my DOM tree at the end I add trigger where needed and element id I'm on, like this:

    $('body').trigger('gridloaded', $(this).attr('id') );

    onClickButton: function(){ $("body").trigger("gridloaded", $(this).attr('id')) }

I'm loving this approach because it's clean: no matter how long the ajax call takes it will always trigger only one event at the right time.

like image 23
Kresimir Pendic Avatar answered Nov 09 '22 21:11

Kresimir Pendic