jQuery DataTables-行点击在第一页以外的页面上不起作用

17
我正在使用DataTables jQuery插件,并在行单击时设置了一个点击处理程序,如下所示:
$('#dt tbody tr').click(function () {
        alert('e');
});

这对DataTables的第一页结果完美地起作用。

然而,当我切换到其他结果页面时,单击处理程序不再注册。

我推测是DataTables代码阻止了click事件传播到我的处理程序,但由于仅在第一页后出现这种情况,因此似乎很不寻常。

因此,有人遇到过(并最好解决了)这个问题吗?

  1. 遇到(并最好解决)此问题
  2. 找到了一种跟踪jQuery / JS事件传播以隔离为什么事件被停止的好方法

干杯


我的假设是不正确的。另一个未声明的假设是:在ajaxComplete中绑定将绑定到所有行,这是无效的,因为DataTables很聪明,直到需要才在浏览器中呈现所有行。因此,Kon的live()答案是正确的。 - Matt Mitchell
请查看Chris Everitt提供的答案。它使用了内置的DataTables函数,而且没有使用已弃用的jquery函数。 - Nullius
5个回答

12

我猜测事件处理程序绑定仅应用于最初加载的行。但是,一旦标记中重新呈现了行集合,事件处理程序就不存在了。

请查看jQuery的live()函数。关键在于事件处理程序绑定到所有符合选择器条件的元素“现在和将来”。


当然,谢谢。虽然它在第一页上有效(所有行都是动态加载的),但我认为这就是答案。我会很快确认并接受。 - Matt Mitchell
2
如果在定义click()处理程序之前加载行,则这是有意义的。 - Kon
当然 - 我把 click 放在我的 ajaxComplete 处理程序中,认为 DataTables 正在加载所有行并将它们隐藏。但是,这仅附加到第一页,因为那是 DataTables 渲染的全部内容(其余内容保留在内存中)。将其设置为 $('#dt tbody tr').live('click', function () 等即可解决此问题(实际上可以在 ajaxComplete 之外声明,因为您提到的“现在和未来”部分)。 - Matt Mitchell
3
请注意,live() 已被弃用,现在应该使用 on() 代替(适用于 jQuery 版本大于 1.7)。请参见 http://api.jquery.com/on/。 - khylo
对我来说,on()函数似乎不起作用...我只是用on()函数替换了live()调用,但它并没有起作用...有什么需要注意的吗? - Rohit Banga

11

在单页面应用程序中,我遇到了这个问题。对于我来说,使用live方法解决了这个问题,但是在提交后没有起作用。我的表格是通过ajax进行填充的,并且用户可以将其销毁并重新创建。

为了修复它,我使用了dataTables.$: "http://datatables.net/api#$"

这是我的解决方法,使用DataTables提供的隐藏行函数示例。

$(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' );
        }
    } );
} );

这应该是被接受的答案。使用已弃用的函数,如jquery live(),从来都不是一个好主意。就像你说的那样,只需使用tableVariable.$('tr')而不是$('#tableId tr')。+1 - Nullius
这也解决了我类似的问题,当我尝试在此博客文章中建议的技术(即将删除确认对话框技术与jQuery数据表一起使用)时,删除链接在第一页后的页面上停止工作。因此,我没有使用$('delete-link').click(function()等...,而是使用上面的想法来解决问题,通过说:oTable.$('.delete-link').on('click', function() { ... }; 在那时,删除链接又开始工作了。 - David Barrows

5

我在所有DataTables行中的按钮上遇到了同样的问题,第一页之后的所有按钮的点击事件都无法工作。 Kon给出了正确的分析(谢谢Kon),但是对于那些寻找示例代码的人,这里是我使用的有效方法:

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

希望这能帮到你!

谢谢。带答案的代码总是很有帮助的。 - bladefist

3
自从"live"被废弃,我建议使用'.on'。这样可以解决您的问题:
$(document).on('click', '.myButton', function() {
    var id = $(this).closest("tr").attr("id");
    var string = 'div_id=' + id;
    alert(string);
       // string sent to processing script here
});

您可以将包含表格的文档与某个父元素交换,这样不太高效。也许尝试使用一个包含您的表格的div元素。

1

我的答案与 @Chris Everitt 的类似,略有不同。只是为了那些想看到它的人..来吧。

 var oTable = $('#masterTable').dataTable( {

                "aLengthMenu": [[5,10, 25, 50, 100 , -1], [5,10, 25, 50, 100, "All"]],
                "iDisplayLength" : 10,
                "aoColumnDefs": [
                             {"sWidth": "25%", "aTargets": [ 0 ] },
                             {"sWidth": "10%", "aTargets": [ 1 ] },
                             {"sWidth": "10%", "aTargets": [ 2 ] },
                             {"sWidth": "10%", "aTargets": [ 3 ] },
                             {"sWidth": "10%", "aTargets": [ 4 ] },
                             {"sWidth": "10%", "aTargets": [ 5 ] },
                             {"sWidth": "15%", "aTargets": [ 6 ] },

                             {"sClass": "align-left" , "aTargets": [ 0,1,4, 2,3,5,6] }              
                         ],

            "aoColumns": [
              { "bSortable": true },
              null, null, null,null, null, 
              { "bSortable": true }
            ]

            });

在表格中注册所有img(dom属性)的事件 -

 oTable.$('td').each( function () {

                    $(this).on('click','img', function () {
                        var nTr = $(this).parents('tr')[0];
                        if ( oTable.fnIsOpen(nTr) )
                        {
                            /* This row is already open - close it */
                            this.src = "${pageContext.request.contextPath}/theme/v_1_0/app-images/details_open.png";
                            oTable.fnClose( nTr );
                        }
                        else
                        {
                            /* Open this row */
                            this.src = "${pageContext.request.contextPath}/theme/v_1_0/app-images/details_close.png";



                            var html = '<div> Placeholder here.. </div>';

                            oTable.fnOpen(nTr, html, 'details');

                           }
                    } );    

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接