113

I have a link, myLink, that should insert AJAX-loaded content into a div (appendedContainer) of my HTML page. The problem is that the click event I have bound with jQuery is not being executed on the newly loaded content which is inserted into the appendedContainer. The click event is bound on DOM elements that are not loaded with my AJAX function.

What do I have to change, such that the event will be bound?

My HTML:

<a class="LoadFromAjax" href="someurl">Load Ajax</a>
<div class="appendedContainer"></div>

My JavaScript:

$(".LoadFromAjax").on("click", function(event) {
    event.preventDefault();
    var url = $(this).attr("href"),
        appendedContainer = $(".appendedContainer");

    $.ajax({
    url: url,
    type : 'get',
    complete : function( qXHR, textStatus ) {           
        if (textStatus === 'success') {
            var data = qXHR.responseText
            appendedContainer.hide();
            appendedContainer.append(data);
            appendedContainer.fadeIn();
        }
      }
    });

});

$(".mylink").on("click", function(event) { alert("new link clicked!");});

The content to be loaded:

<div>some content</div>
<a class="mylink" href="otherurl">Link</a>
fourpastmidnight
  • 4,032
  • 1
  • 35
  • 48
Michael
  • 32,527
  • 49
  • 210
  • 370

11 Answers11

274

Use event delegation for dynamically created elements:

$(document).on("click", '.mylink', function(event) { 
    alert("new link clicked!");
});

This does actually work, here's an example where I appended an anchor with the class .mylink instead of data - http://jsfiddle.net/EFjzG/

dsgriffin
  • 66,495
  • 17
  • 137
  • 137
  • 1
    This is what I wrote that I did. – Michael May 16 '13 at 22:05
  • @confile Really? I've read your question twice and don't see it either in writing or in code? – dsgriffin May 16 '13 at 22:06
  • @confile.. See the answer agian .. that's different from what you have – Adil Shaikh May 16 '13 at 22:06
  • @Zenith I added a Not to my question at the bottom. What you wrote is also not working for me. – Michael May 16 '13 at 22:09
  • 2
    @confile My answer does work!! here's an example of it - http://jsfiddle.net/EFjzG/ – dsgriffin May 16 '13 at 22:17
  • 1
    Hi, this answer is working just fine. Event is attached on whole document, so basically every click on page is triggering event, but then, selector '.mylink' is applied to filter click events we need. Excellent technique. – Emir Sep 19 '14 at 09:12
  • @d.g this answer is good.but how Can I do this in pure js without jquery? –  Jun 25 '16 at 11:25
  • 2
    The answer is correct (just wanted to enforce it). $(".mylink").on("click", function(event) { alert("new link clicked!");}); is not the same as $(document).on("click", '.mylink', function(event) { alert("new link clicked!"); }); – Paulo Henrique Nov 07 '18 at 17:21
  • 1
    Thank you, this solution helped me to solve the problem at ajax loaded webform ... What is the reason for this problem? – drupalfan Jun 23 '22 at 11:53
  • @drupalfan read more in this answer: https://stackoverflow.com/a/31236491/9022150 It's about how the js engine works under the hood, setting up couple of things (like in this case: event bindings) based on the initial html document, so not everything is "live" later on, thus it requires these "helping techniques" here and then to fully stay present.. ;) – Viktor Borítás Oct 03 '22 at 00:43
29

If the content is appended after .on() is called, you'll need to create a delegated event on a parent element of the loaded content. This is because event handlers are bound when .on() is called (i.e. usually on page load). If the element doesn't exist when .on() is called, the event will not be bound to it!

Because events propagate up through the DOM, we can solve this by creating a delegated event on a parent element (.parent-element in the example below) that we know exists when the page loads. Here's how:

$('.parent-element').on('click', '.mylink', function(){
  alert ("new link clicked!");
})

Some more reading on the subject:

Kai
  • 2,699
  • 1
  • 12
  • 7
  • 4
    I prefer this answer to the one by @lifetimes, because it tells me to set the handler to some parent element that is present at load time, not necessarily all the way up to _document_. This makes the selector in the second argument to `on` less prone to unintended matches. – R. Schreurs Jul 09 '18 at 15:01
  • If the ajax loaded html class also parent-element then its not working – Jafar Pinjar Oct 22 '19 at 06:22
7

if your question is "how to bind events on ajax loaded content" you can do like this :

$("img.lazy").lazyload({
    effect : "fadeIn",
    event: "scrollstop",
    skip_invisible : true
}).removeClass('lazy');

// lazy load to DOMNodeInserted event
$(document).bind('DOMNodeInserted', function(e) {
    $("img.lazy").lazyload({
        effect : "fadeIn",
        event: "scrollstop",
        skip_invisible : true
    }).removeClass('lazy');
});

so you don't need to place your configuration to every you ajax code

antoniputra
  • 4,251
  • 6
  • 26
  • 31
2

As of jQuery 1.7, the .live() method is deprecated. Use .on() to attach event handlers.

Example -

$( document ).on( events, selector, data, handler );
bozzmob
  • 12,364
  • 16
  • 50
  • 73
Elnaz
  • 2,854
  • 3
  • 29
  • 41
1

For those who are still looking for a solution , the best way of doing it is to bind the event on the document itself and not to bind with the event "on ready" For e.g :

$(function ajaxform_reload() {
$(document).on("submit", ".ajax_forms", function (e) {
    e.preventDefault();
    var url = $(this).attr('action');
    $.ajax({
        type: 'post',
        url: url,
        data: $(this).serialize(),
        success: function (data) {
            // DO WHAT YOU WANT WITH THE RESPONSE
        }
    });
});

});

1

If your ajax response are containing html form inputs for instance, than this would be great:

$(document).on("change", 'input[type=radio][name=fieldLoadedFromAjax]', function(event) { 
if (this.value == 'Yes') {
  // do something here
} else if (this.value == 'No') {
  // do something else here.
} else {
   console.log('The new input field from an ajax response has this value: '+ this.value);
}

});
ChristianG
  • 458
  • 4
  • 11
0

use jQuery.live() instead . Documentation here

e.g

$("mylink").live("click", function(event) { alert("new link clicked!");});
ROMMEL
  • 524
  • 2
  • 10
0

For ASP.NET try this:

<script type="text/javascript">
    Sys.Application.add_load(function() { ... });
</script>

This appears to work on page load and on update panel load

Please find the full discussion here.

Mohd Abdul Mujib
  • 13,071
  • 8
  • 64
  • 88
Michael
  • 173
  • 1
  • 3
0

Important step for Event binding on Ajax loading content...

01. First of all unbind or off the event on selector

$(".SELECTOR").off();

02. Add event listener on document level

$(document).on("EVENT", '.SELECTOR', function(event) { 
    console.log("Selector event occurred");
});
Kaushal Sachan
  • 1,175
  • 11
  • 8
0

Here is my preferred method:

// bind button click to function after button is AJAX loaded
$('#my_button_id').bind('click', function() {
    my_function(this);
});

function my_function () {
    // do stuff here on click
}

I place this code right after the AJAX call is complete.

kintsukuroi
  • 1,332
  • 16
  • 15
0

I would add one point that was NOT obvious to me as a JS newb - typically your events would be wired within document, e.g.:

$(function() {
    $("#entcont_table tr td").click(function (event) {
    var pk = $(this).closest("tr").children("td").first().text();
    update_contracts_details(pk);
});
}

With event delegation however you'd want:

$(function() {
    // other events
}

$("#entcont_table").on("click","tr td", function (event) {
    var pk = $(this).closest("tr").children("td").first().text();
    update_contracts_details(pk);
});

If your event delegation is done within the document ready, you'll an error of the like:

cant assign guid on th not an boject
logicOnAbstractions
  • 2,178
  • 4
  • 25
  • 37