Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery DataTables - Row click not registering on pages other than first

I'm using the DataTables jQuery Plugin and have a click handler setup on row click as follows:

$('#dt tbody tr').click(function () {
        alert('e');
});

This works perfectly for the first page of DataTables results.

However, when I move to another page of results, the click handler no longer registers at all.

My presumption is that the DataTables code is stopping the propogation of the click event to my handler, but as this is only occurring on pages after the first it seems unusual.

As such, has anyone:

  1. Encountered (and ideally resolved) this problem
  2. Found a good way to track jQuery/JS event propogation to isolate why the event is being stopped

Cheers

like image 864
Matt Mitchell Avatar asked May 12 '11 23:05

Matt Mitchell


3 Answers

I'm guessing the event handler binding is being applied only to the initially loaded rows. But once the row collection gets re-rendered in the markup, the event handlers are no more.

Check out jQuery's live() function. The key there being that event handlers are bound for all elements meeting selector criteria "now and in the future."

like image 137
Kon Avatar answered Nov 02 '22 07:11

Kon


I had this problem on a single page application. The live method worked for me except after a postback. My table was populated via ajax, and the user could cause it to be destroyed and recreated.

To fix it I used dataTables.$: "http://datatables.net/api#$"

Here is my fix using the example DataTables give for the hidden row function.

$(document).ready(function() {
    /*
    * Insert a 'details' column to the table
    */
    var nCloneTh = document.createElement( 'th' );
    var nCloneTd = document.createElement( 'td' );
    nCloneTd.innerHTML = '<img src="../examples_support/details_open.png">';
    nCloneTd.className = "center";

    /* CHANGE: Remove all the expand control elements we may have added earlier
    * or else you'll add a new column for every postback
    */
    $('.expand-control').remove();

    /*
    * CHANGE: Add the expand-control class to these elements,
    * so we can remove them after a postback
    */
    $(nCloneTh).addClass('expand-control');
    $(nCloneTd).addClass('expand-control');

    $('#example thead tr').each( function () {
        this.insertBefore( nCloneTh, this.childNodes[0] );
    } );

    $('#example tbody tr').each( function () {
        this.insertBefore(  nCloneTd.cloneNode( true ), this.childNodes[0] );
    } );

    /*
    * Initialse DataTables, with no sorting on the 'details' column
    */
    var oTable = $('#example').dataTable( {
        "aoColumnDefs": [
            { "bSortable": false, "aTargets": [ 0 ] }
        ],
        "aaSorting": [[1, 'asc']]
    });

    /* Add event listener for opening and closing details
    * Note that the indicator for showing 
    * which row is open is not controlled by DataTables,
    * rather it is done here
    */

    /* CHANGE:  Here I use jQuery.dataTable.$ instead of
    * jQuery('#example tbody td img'),
    * this is what preserves the event handler on the 2nd (etc) 
    * pages after a postback
    * Note the use of on instead of live, recommended over live as of 1.7 
    */
    oTable.$('tr').find('img').on('click', function () {
        var nTr = $(this).parents('tr')[0];
        if ( oTable.fnIsOpen(nTr) )
        {
            /* This row is already open - close it */
            this.src = "../examples_support/details_open.png";
            oTable.fnClose( nTr );
        }
        else
        {
            /* Open this row */
            this.src = "../examples_support/details_close.png";
            oTable.fnOpen( nTr, fnFormatDetails(oTable, nTr), 'details' );
        }
    } );
} );
like image 45
Chris Everitt Avatar answered Nov 02 '22 06:11

Chris Everitt


I had the same issue with buttons in all of my DataTables rows, the click event didn't work on any buttons after the first page of results. Kon gave the correct analysis (thank you Kon), but for those looking for example code, here's what worked for me:

$('.myButton').live('click', function() {
    var id = $(this).closest("tr").attr("id");
    var string = 'div_id=' + id;
    alert(string);
       // string sent to processing script here
});

Hope that helps!

like image 20
BD_Design Avatar answered Nov 02 '22 08:11

BD_Design