jQuery DataTables - 行单击未在第一个以外的页面上注册

Posted

技术标签:

【中文标题】jQuery DataTables - 行单击未在第一个以外的页面上注册【英文标题】:jQuery DataTables - Row click not registering on pages other than first 【发布时间】:2011-08-24 13:26:56 【问题描述】:

我正在使用DataTables jQuery Plugin,并在行点击时设置了点击处理程序,如下所示:

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

这非常适用于 DataTables 结果的第一页。

但是,当我移动到另一页结果时,点击处理程序根本不再注册。

我的假设是 DataTables 代码正在停止向我的处理程序传播 click 事件,但由于这仅发生在第一个之后的页面上,这似乎不寻常。

因此,有没有人:

    遇到(并理想地解决了)这个问题 找到了一种跟踪 jQuery/JS 事件传播的好方法,以找出事件停止的原因

干杯

【问题讨论】:

我的假设是错误的。另一个未说明的假设:ajaxComplete 中的绑定将绑定到所有行,这是无效的,因为 DataTables 是明智的,并且在需要之前不会在浏览器中呈现所有行。因此,Kon 对live() 的回答是正确的。 请查看 Chris Everitt 提供的答案。它使用内置的 DataTables 函数,并且不使用已弃用的 jquery 函数。 【参考方案1】:

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

查看 jQuery 的 live() 函数。关键是事件处理程序必须针对“现在和将来”满足选择器标准的所有元素。

【讨论】:

当然,干杯。奇怪的是它在第一页上工作(所有行都是动态加载的),但我认为这就是答案。我会尽快确认并接受。 如果您在定义 click() 处理程序之前加载行是有道理的。 当然——我将click 放在我的ajaxComplete 处理程序中,认为DataTables 正在加载所有行并只是隐藏它们。但是,这仅附加到第一页,因为这是所有 DataTables 呈现(其余部分保存在内存中)。让它$('#dt tbody tr').live('click', function () 等修复它(实际上可以在ajaxComplete 之外声明,因为你提到的“现在和未来”位。 请注意 live() 已被弃用,您现在应该使用 on() 代替(对于 jquery > 1.7)。见api.jquery.com/on 对我来说 on() 似乎不起作用...我只是用 on() 函数替换 live() 调用,但它不起作用...任何警告?【参考方案2】:

我在单页应用程序上遇到了这个问题。在回发后,live 方法对我有用except。我的表是通过 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 这也解决了我在尝试使用此博客文章中建议的技术时遇到的类似问题:ricardocovo.com/2010/09/02/…(即,将删除确认对话框技术与 jQuery 数据表结合使用); ...删除链接在第一页之后的页面上停止工作;所以我没有使用 $('delete-link').click( function () etc ... ,而是使用上面的想法来解决问题,方法是: oTable.$('.delete-link').on( 'click', function() ... ; 此时删除链接再次开始工作。【参考方案3】:

我的所有 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
);

希望对您有所帮助!

【讨论】:

谢谢。带有答案的代码总是有帮助的【参考方案4】:

由于 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
);

您可以将 document 与一些父元素交换,因为它不是很有效。也许尝试使用包含您的表格的 div。

【讨论】:

【参考方案5】:

我的回答与@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 attr's) 注册事件 -

 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');

                           
                     );    

【讨论】:

以上是关于jQuery DataTables - 行单击未在第一个以外的页面上注册的主要内容,如果未能解决你的问题,请参考以下文章

JQuery DataTables - 删除 fnFilter 并显示所有结果

Datatables Jquery 通过单击 TR 展开/折叠

保持启用的复选框在 jQuery DataTables 的顶部,尽管排序顺序

JQuery1.8 Datatables单击按钮保存状态

使用 DataTables 插件隐藏特定行?

jQuery DataTables 检查标题单击时的复选框