views:

762

answers:

4

I am trying to use the delegate method on a grid that I wrap with the DataTables.Net plug-in. I originally had this code which works as expected.

    $("#myGrid tbody tr").click(function() {
        var id = $(this).children('td').eq(0).text();
        alert(id);
    });

However, if I change the paging size then the newer rows don't have the click event calling the function. I decided the new JQuery delegate method should do exactly what I wanted; however, it does nothing at all on any tr element.

Could anyone explain why this does not work :

    $('#myGrid tbody').delegate('tr', 'click', function() {
        var id = $(this).children('td').eq(0).text();
        alert(id);
    }); 

I have tried different combinations of the selector and none get it to work.

Thanks Paul Speranza

+1  A: 

Use this:

$("#myGrid tbody tr").live('click', function() {
    var id = $(this).children('td').eq(0).text();
    alert(id);
});

.live() works for current of future elements.

Nick Craver
That's exactly what `delegate` is for, except it has better performance, due to less required bubbling of events.
Alex Sexton
As does `delegate`. I suggest you read up on it.
miketaylr
Thank you guys, I was avoiding 'live' because I thought that delegate was supposed to replace it. I still do not understand why delegate doesn't work for me, but live does and everything is worling as expected. Once again, thanks for the quick responses!
Paul Speranza
@Paul it doesn't work because your grid is being replaced. If you wanted to use delegate you'd have to attach it above the elements that get replaced. In Alex's example the event is attached to the grid instead of document like live does by default...which this is more efficient as it means fewer bubbles, it doesn't help if that element gets blown away as part of your AJAX load. That's why it doesn't work in this case...the element listening doesn't exist. If you had a div on the outside `id="wrapper"`, then this would work: `$('#wrapper').delegate('#myGrid tr','click', function() {...`
Nick Craver
@Alex - While that's normally true, if you're attaching to an element replaced as part of the ajax callback, it's useless. Whether it's `.live()` with a narrower context or `.delegate()`, either one needs to be on an element that's not being replaced...since I don't know what that is here, `.live()` is the certain option for it working.
Nick Craver
This does everything except answer the question "why is delegate method not working" - confusing that it's selected as the answer. Delegate _does_ replace live. It will likely be deprecated in future versions. It is a better use of event delegation in every facet.
Alex Sexton
Nick, thanks for your reply. It makes total sense. And I do have a wrapper that I could have be the high level element. You just have to love Stack Overflow!
Paul Speranza
@Nick - agreed, I believe I mentioned that in my answer, that the tbody was likely being manipulated and ruining the delegation.
Alex Sexton
@Alex - It wasn't the tbody like you stated, it was the entire table being destroyed, hence the problem. `#myGrid` is the table. This is why I clarified what's happening in comments. If you look at my explanation in the 4th comment, I state exactly *why* it's not working...
Nick Craver
A: 

If the newer rows are being added dynamically, you have to use live method on the items, change the delegate to live

Teja Kantamneni
I think you misunderstand what `delegate` does--it's just event delegation like `live`.
miketaylr
`delegate` uses `live` at it's core, however it has better performance than live by using event delegation on a common ancestor that is not the base document.
Alex Sexton
+2  A: 

Try this instead:

$('#myGrid').delegate('tr', 'click', function() {
  var id = $(this).children('td').eq(0).text();
  alert(id);
});

There's a good chance that some events on your tbody are getting messed with and/or your tbody's are getting manipulated. I doubt the entire table suffers from this problem as well.

Alex Sexton
Note that this could potentially be several times faster than using `live` depending on how your dom is structured.
Alex Sexton
A: 

Try this

$('#myGrid tbody').delegate('click', 'tr', function() {
    var id = $(this).children('td').eq(0).text();
    alert(id);
});

or

$('body').delegate('click', '#myGrid tbody tr', function() {
    var id = $(this).children('td').eq(0).text();
    alert(id);
}); 
Ipog