Event Delegation on selector that's returned from an ajax response

The summary of this question is: if we’re using Event Delegation does it always have to be bound to an element that exists in the DOM on page load? Can we bind to a selector returned in an ajax response?

I’m using jQuery 3.2.1 and have been reading about Event Delegation: http://learn.jquery.com/events/event-delegation/

Using their example markup:

<ul id="list">
    <li><a href="http://domain1.com">Item #1</a></li>
    <li><a href="/local/path/1">Item #2</a></li>
    <li><a href="/local/path/2">Item #3</a></li>
    <li><a href="http://domain4.com">Item #4</a></li>
</ul>

I understand the point they’re making about how if we added a 5th item to #list with js, the following would only work for Items 1 – 4 because the 5th item didn’t exist when .on was called and therefore doesn’t get the event handler:

$( "#list a" ).on( "click", function( event ) {
});

So the solution given is use a delegated event handler like this:

$( "#list" ).on( "click", "a", function( event ) {
});

In both of these cases they have targeted #list because that’s there on page load.

In my application, I am making an ajax request which would return the equivalent of the entire block of markup given at the start (i.e. everything including #list) and appending it to a Bootstrap 3.3.7 modal window with an ID, #notifierModal inside the default area for content which has a class of .modal-body:

$.ajax({
    url: $(this).attr('href'),
    method: 'get'
}).done(function(response) {
    $('.modal-body').html(response);
    $('#notifierModal').modal('show');
}); 

I have this present on page load:

$( "#list" ).on( "click", "a", function( event ) {
    console.log('something inside #list was clicked');
});

This does not work – presumably because #list is not there on page load since it’s appended to .modal-body after the ajax request completes.

This does work – presumably because .modal-body is present on page load:

$( ".modal-body" ).on( "click", "a", function( event ) {
    console.log('something inside .modal-body was clicked');
});

So my question is two-fold:

  1. If we’re using Event Delegation does it always have to be bound to an element that exists in the DOM on page load? Is it possible to target a selector that’s returned in an ajax response?

  2. The reason this is a problem in my application is because I have other anchor tags inside .modal-body which I don’t want to be handled by the click event given in my js. It seems impossible to target anchors inside #list in this way? How could I write the js such that it only targets anchors inside #list?

PS – I’ve read Event binding on dynamically created elements? but this seems to address binding on an element that existed on page load.

125 thoughts on “Event Delegation on selector that's returned from an ajax response”

Leave a Comment