1

My regular onclick event, like so works:

$(document).ready(function () {
    $("#guestlist .viewguestdetails").click(function () {        
        $(".guestdetails[data-id='18']").toggle();
    });
});

However, when that onclick event is on dynamic HTML, a row I'm inserting into a table, it no longer works. As in: nothing happens. So I checked out this post: Event binding on dynamically created elements?

And as answered in there went for .on() method.

I added a class newrow to this tr element and now have this:

$(document).ready(function () {
    $('.newrow').on('click', 'span', function () {
        $(".guestdetails[data-id='" + $(this).attr('data-id') + "']").toggle();
    });
}); 

Here I'm building a new row and inserting that:

    var newrow='';

    newrow += '<tr class="newrow" data-id="' + id + '">';

    newrow += '<td class="alignleft sorting_1"><span class="viewguestdetails" data-id="' + id + '">' + firstname + ' ' + lastname + '</span>';               
    newrow += '&nbsp;&nbsp;<span class="completeguestdetails" data-id="' + id + '">(' + $("#completedetails").attr('data-message') + ')</span><br/>';

    newrow += '<div class="guestdetails" data-id="' + id + '">';
    newrow += SOME DATA';
    newrow += '</div>';
    newrow += '</td>';

    //add checkboxes
    var checkstatus = 'off';
    newrow += '<td><span class="attendance checkbox-' + checkstatus + '" data-id="' + id + '" data-daypart="day"></span></td>';
    newrow += '<td><span class="attendance checkbox-' + checkstatus + '" data-id="' + id + '" data-daypart="ceremony"></span></td>';
    newrow += '<td><span class="attendance checkbox-' + checkstatus + '" data-id="' + id + '" data-daypart="reception"></span></td>';
    newrow += '<td><span class="attendance checkbox-' + checkstatus + '" data-id="' + id + '" data-daypart="diner"></span></td>';
    newrow += '<td><span class="attendance checkbox-' + checkstatus + '" data-id="' + id + '" data-daypart="party"></span></td>';
    newrow += '</tr>';

    //add the row to the guestlist table
    $('#guestlist tbody').prepend(newrow);  

I used jQuery debugger (https://chrome.google.com/webstore/detail/jquery-debugger/dbhhnnnpaeobfddmlalhnehgclcmjimi) and found that on the inserted row or on the span tags inside it, there are no jQuery events attached.

What am I missing?

UPDATE I added this and moved it outside the document.ready() function. In that case the events are attached:

$('#guestlist').on('click', 'span.viewguestdetails', function () {
    $(".guestdetails[data-id='" + $(this).attr('data-id') + "']").toggle();
});

But then the already existing rows no longer work. May that be because I still have this in my document.ready():

$("#guestlist .viewguestdetails").click(function () {        
    $(".guestdetails[data-id='" + $(this).attr('data-id') + "']").toggle();
});

So, right now, either the newly inserted row functions correct OR the already existing rows function correct.

Why?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Adam
  • 6,041
  • 36
  • 120
  • 208

3 Answers3

1

The point of event delegation is to use a element of the DOM that was present when the page rendered. As I understand your .newrowwas not. So try:

$(document).on('click', '.newrow span', function () {

From jQuery documentation: 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().

Sergio
  • 28,539
  • 11
  • 85
  • 132
  • This works! What I do find strange is that when I replace 'document' with '#guestdetails' or 'tbody', which are both parents of the newly inserted row, it no longer works. Both these elements are, like you also mention, present when the page rendered. How is that possible? – Adam Sep 16 '13 at 19:03
  • @Flo, without seeing your markup I cannot tell. Event handlers are removed in case the element is replaced, could that be the case? Anyway, glad its working now :) – Sergio Sep 16 '13 at 19:06
  • I updated my post, since when adding your code, the existing rows no longer work. I noticed Greg Greg Borenstein also mentions something about this right here, but don't know if that's it or how to apply that: http://stackoverflow.com/questions/203198/event-binding-on-dynamically-created-elements – Adam Sep 16 '13 at 19:10
  • 1
    @Flo, were in your page is your code? after or before the html? Try having all your jQuery after the html, at bottom, before the `

    ` tag. (for debugging purposes). Oterwise when the code is outside the .ready() function and before the html has been read It will not work because the elements of the DOM are not there yet.

    – Sergio Sep 16 '13 at 19:13
  • @Flo, good with live link. Will check in a while, I'll post back – Sergio Sep 16 '13 at 20:05
  • 1
    @Flo, I have to go to bed now. I think you have the code you added on your edit 2 times now. One outside the ready function and one inside. They both fire and make a toggle. Which means nothing happens :) I added that code again in my console and it worked. I suspected first of the datatable removing the event listeners when declared. Can you remove the duplicate event listeners and try that? – Sergio Sep 16 '13 at 20:49
1

part that says:

 $('.newrow').on('click', 's...

should actualy be:

 $('parentOfnewrowElement').on('click', '.newrow span...

what you were doing was binding event to all .newRow elements currently existing in document. what you should do is to bind event to the first parent that doesn't get removed from document.

dee zg
  • 13,793
  • 10
  • 42
  • 82
0

Try this instead:

$(document).on('click', '.newrow span', function () {

The element you want to bind the event to needs to exist when the page has loaded.

j08691
  • 204,283
  • 31
  • 260
  • 272