Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding events to ajax appended content [duplicate]

Let's say I have some of links that I want to add a javascript action to:

<a class='test'>
<a class='test'>
<a class='test'>

When my page loads I give them all a click event:

$('.test').click(function(){
  alert("I've been clicked!")
});

but let's say afterward I add another element and I want to give it the same event. I can't do this:

$('.test').click(function(){
  alert("I've been clicked!")
});

because then the first 3 will have 2 events on them. What's the best way to deal with this?

like image 712
pguardiario Avatar asked Dec 12 '22 01:12

pguardiario


2 Answers

You can bind the $.on to a parent element that will always exist in dom like this.

$(document).on('click','.test', function() {
            console.log('Test clicked');
        });

Note that: You can replace document with any parent of the element that will always exist in dom, and the closer the parent the better.

Simple event binding with click wont work as click bind the event handlers to elements that already exists in dom at the time of binding. And hence it doesn't work for elements dynamically added to dom later through Ajax or jQuery. For that purpose you have to use event delegation. And you can use $.on for that purpose.

Check documentation of $.on

You can use $.live but $live is depreciated. use $.on instead. Equivalent syntax of $.on for $.live and $.delegate which does the same thing

$(selector).live(events, data, handler);                // jQuery 1.3+
$(document).delegate(selector, events, data, handler);  // jQuery 1.4.3+
$(document).on(events, selector, data, handler);        // jQuery 1.7+

In this case event handler will be bound to document. And events will be delegated to target element by jQuery in this case test class.

UPDATE

I would suggest you to use $.on for all event handling purposes as all other methods routes through $.on and $.off method under the hood.

Check the definition of these functions from jQuery source v.1.7.2

bind: function( types, data, fn ) {
    return this.on( types, null, data, fn );
},
unbind: function( types, fn ) {
    return this.off( types, null, fn );
},

live: function( types, data, fn ) {
    jQuery( this.context ).on( types, this.selector, data, fn );
    return this;
},
die: function( types, fn ) {
    jQuery( this.context ).off( types, this.selector || "**", fn );
    return this;
},

delegate: function( selector, types, data, fn ) {
    return this.on( types, selector, data, fn );
},
undelegate: function( selector, types, fn ) {
    // ( namespace ) or ( selector, types [, fn] )
    return arguments.length == 1? this.off( selector, "**" ) : this.off( types, selector, fn );
} 

And that is true for these convenient events handlers too

blur focus focusin focusout load resize scroll unload click dblclick mousedown 
mouseup mousemove mouseover mouseout mouseenter mouseleave change select 
submit keydown keypress keyup error contextmenu

You can see all methods are using $.on and $.off themselves. So using $.on you can at least save a function call though which isn't that significant in most of the cases.

like image 175
Prasenjit Kumar Nag Avatar answered Dec 26 '22 19:12

Prasenjit Kumar Nag


As your .test are appended via ajax, so you need delegate event on that, ordinary binding will not affect them. Delegate binding will applied to all elements existing in DOM and will add to DOM.

$('body').on('click', '.test', function() {
   // your code
});

Instead of body you can use the container of all .test which already belongs to DOM.

Get more about .on()

You can also use .delegate() like following:

$('#container').delegate('.test', 'click', function() {
   // your code
});
like image 38
thecodeparadox Avatar answered Dec 26 '22 20:12

thecodeparadox