Clickable rows after sorting the table

Clickable rows after sorting the table

kendrickjoshkendrickjosh Posts: 14Questions: 0Answers: 0
edited May 2012 in Bug reports
In my data tables usage, each row is clickable. When I sort the table, and rows come in from other pages (for example I have 2 pages worth of data, if when I sort data comes into the first page from the second page), the rows that appear are not clickable, whereas the rows from the first page are still clickable. Is there something I might not be doing correctly? I add a click handler to all my rows by doing this:

$('#nameOfTable tbody tr').click( function( e ) {
... etc ...

is there some reason why that wouldn't be applied to the rows from the second page of incidents?

Thanks

Replies

  • jcreadyjcready Posts: 44Questions: 0Answers: 0
    [code]$('#nameOfTable').on('click', 'tr', function( e ) { ... });[/code]
  • kendrickjoshkendrickjosh Posts: 14Questions: 0Answers: 0
    are you saying this is what I should have instead? Can you tell me what the difference is?
  • allanallan Posts: 63,542Questions: 1Answers: 10,476 Site admin
    Have a look at the top FAQ: http://datatables.net/faqs#events :-)

    Allan
  • jcreadyjcready Posts: 44Questions: 0Answers: 0
    edited May 2012
    [code].click(myEventHandler)[/code]

    This will attach the event handler to all matching elements at the time you call it, meaning when you called it jQuery looked for any matching elements in the DOM and attached your handler to them. But when you loaded the second page, none of those new elements were in the DOM when you called .click() so none of them have any event handlers attached to them.

    [code].on('click', 'tr', myEventHandler)[/code]

    See: http://api.jquery.com/on/

    As of jQuery 1.7, the .on() method provides all functionality required for attaching event handlers. The .on() method attaches event handlers to the currently selected set of elements in the jQuery object and have the advantage that they can process events from descendant elements that are added to the document at a later time.

    In addition to their ability to handle events on descendant elements not yet created, another advantage of delegated events is their potential for much lower overhead when many elements must be monitored. On a data table with 1,000 rows in its tbody, this example attaches a handler to 1,000 elements:

    [code]$('#dataTable tbody tr').click(function(event){
    alert($(this).text());
    });[/code]

    A delegated-events approach attaches an event handler to only one element, the tbody, and the event only needs to bubble up one level (from the clicked tr to tbody):

    [code]$('#dataTable tbody').on('click', 'tr', function(event){
    alert($(this).text());
    });[/code]
  • kendrickjoshkendrickjosh Posts: 14Questions: 0Answers: 0
    Thank you both. Very helpful! From the posts I was able to put together:

    I need to use post-initialization
    I need to make use of the on method

    So this is what I have now, but now it seems none of the rows are clickable:

    $(tableVariableName.fnGetNodes()).on('click', 'tr', function( e ) {
    ...
    }

    does anything seem wrong with that?

    pretty close to right before the above line i do call

    $('#tableNameinHTML').dataTable().fnClearTable();
    $('#tableNameinHTML').dataTable().fnAddData(allRows);
  • allanallan Posts: 63,542Questions: 1Answers: 10,476 Site admin
    edited May 2012
    > does anything seem wrong with that?

    Yes - don't use fnGetNodes with 'live' events - it won't work. Do what jcready suggests with "$('#dataTable tbody').on('click', 'tr', function(event){" .

    *edit* Perhaps I should elaborate on why it won't work. fnGetNodes will return a list of all TR elements, which jQuery will then use - but with delegate events, the element matched is the one that is assigned the event handler and events bubble up from the lower elements (technically not quite right, but good enough for this moment :-) ). Hence why jcready's selector is getting the tbody as the base element.

    Allan
  • kendrickjoshkendrickjosh Posts: 14Questions: 0Answers: 0
    Sorry to keep asking questions, but I'd like to try to understand. Why does fnGetNodes not work with 'live' events?
  • allanallan Posts: 63,542Questions: 1Answers: 10,476 Site admin
    See my edit above - but explaining that a bit further, because fnGetNodes returns an array of the actual TR elements, not the parent's container. So you can't apply a 'live' or delegated event since you are giving jQuery a set of DOM nodes to work with, not a selector that can be run at any time.

    Allan
  • kendrickjoshkendrickjosh Posts: 14Questions: 0Answers: 0
    I think that makes sense. Thank you.
  • kendrickjoshkendrickjosh Posts: 14Questions: 0Answers: 0
    So since I've been testing and debugging this more I've discovered an issue that this change has created. I've got a process where you can click one of the rows, edit it in a side table, and when the http request comes back, I clear and re-add all the data. This worked fine with the old line I had:

    $('#incidentTable tbody tr').click( function( e ) {

    But changing to this one:

    $('#incidentTable tbody').on('click', 'tr', function( e ) {

    causes it not to work when the http request comes back and I clear and re-add the data. I've put some alerts in to try to figure out what's going on and it seems like when I click on a row after the request has come back, the click is run twice. Does that make sense at all?
  • kendrickjoshkendrickjosh Posts: 14Questions: 0Answers: 0
    edited May 2012
    or even I'm seeing three times now. I'm wondering if maybe everytime I call that method, a new listener is registered maybe?

    which actually might make sense in regards to the help you already gave me. The reason I did have it re-adding click handlers everytime I reloaded the table was because it seemed the click handlers were removed everytime I reloaded the table. That was using the old method, using 'live' selectors. Since I'm not doing that anymore, I only need to add the click method once.

    I tried it and that fixed it.
    Thanks!
  • allanallan Posts: 63,542Questions: 1Answers: 10,476 Site admin
    > or even I'm seeing three times now. I'm wondering if maybe everytime I call that method, a new listener is registered maybe?

    Yes - just add it once to the document, not in a callback. See this example (which uses the older 'live' method, but still shows the idea): http://datatables.net/release-datatables/examples/advanced_init/events_live.html

    Allan
This discussion has been closed.