【问题标题】:How do you programatically open multiple rows in DataTables您如何以编程方式在 DataTables 中打开多行
【发布时间】:2018-10-31 09:43:51
【问题描述】:

我认为这个问题会得到回答,但我无法解决这个问题。试过了:

我在 serverSide 模式下使用 DataTables 1.10.16 - 我的数据是通过 ajax 加载的,而不是在页面加载时加载。

我的标记只是一个带有 ID 的表格,#substancesTable

<table id="substancesTable" cellspacing="0" width="100%">
    <thead>
        <tr>
            <th>ID</th>
            <th>EC</th>
            <th>CAS</th>
            <th>Name</th>
         </tr>
     </thead>
</table>

加载数据的js如下:

var substancesTable = $('#substancesTable').DataTable({
    "processing": true,
    "serverSide": true,
    "searching": false,
    "ajax": {
        "url": "/get-substances.json",
        "dataSrc": function (json) {
             return json.data;
        }
    }
});

这很好地填充了我的表格。我有一个事件处理程序,这样当用户手动单击一行(#substancesTable 内的任何&lt;td&gt; 元素)时,它会发出进一步的 ajax 请求以获取更多数据,然后将这些数据填充到用户的 &lt;td&gt; 中点击。此代码还负责关闭/折叠任何打开的行:

$('#substancesTable tbody').on('click', 'td', function () {
    var tr = $(this).closest('tr');
    var row = substancesTable.row( tr );

    if ( row.child.isShown() ) {
        row.child.hide();
        tr.removeClass('shown');
    }
    else {
        row.child( expand_substance(row.data()) ).show();
        tr.addClass('shown');
    }
} );

上面的代码调用了一个函数expand_substance 来处理上面提到的ajax 请求。这一切都很好。

我想做的是找到一种以编程方式打开某些行的方法。我的意思是拥有一组用户点击的行 ID,例如

var openRows = [5, 6, 8, 33, 100];

此数组数据将存储在 Redis(缓存)中,因此如果用户离开页面,当他们返回时,openRows 中的数据将被加载,我想打开相应的行。但我不知道如何告诉 DataTables 打开第 5、6、8、33、100 行等。

上面的链接似乎对我不起作用。例如,如果我尝试:

substancesTable.row(':eq(0)', { page: 'current' }).select();

我收到控制台错误:

VM308:1 Uncaught TypeError: substancesTable.row is not a function

我不确定这是否是打开该行的方法,但找不到更多有用的信息。

那么,是否可以使用 JavaScript 根据一组已知 ID (openRows) 打开表格的某些行?

【问题讨论】:

  • 你可以做类似openRows.each(function({ $(this).show()});的事情吗?
  • 我不确定您在什么时候尝试调用 row() 但它看起来不像是基于错误的 DataTable API 的引用。可能物质表在调用 row() 之前被重新分配给其他东西。您可以通过再次调用 $("#substancesTable").DataTable() 来获取对已初始化 DT 的引用,而无需传递任何选项。
  • @PaulZepernick 谢谢。页面呈现后,我在控制台中使用它。我尝试使用$("#substancesTable").DataTable().row(':eq(o)', {page: 'current'}).select();,但出现错误 - “VM967:1 Uncaught TypeError: $(...).DataTable(...).row(...).select is not a function”
  • api 文档中返回的行对象没有 select() 方法:datatables.net/reference/api 你可以做 row(..).child().show() 或 row(..) .child().hide()
  • 我刚刚注意到您将链接放在文档中... select() 方法显然是一些默认情况下不存在的 DataTable 扩展。我不熟悉它,但我的猜测是扩展没有加载。这位于提供的链接中文档的顶部“请注意 - 此属性需要 DataTables 的 Select 扩展。”

标签: javascript jquery datatables


【解决方案1】:

解决这个问题很有趣(希望我做到了)...因为它相当复杂和棘手。

首先,我不得不提一下,使用服务器端功能构建演示是不可能的(或者至少很痛苦),所以我使用了 DataTable 的"zero configuration" example

现在,我希望我能正确理解行索引数组是从用户行点击中预先存储的......并且这是当前问题的起点,即重用该数组来操作行。

在我的示例中,只有 57 行...所以我使用了这个数组:var targets = [5, 6, 8, 33]

一步一步解决:

  1. 使用 drawCallback 在数组上运行 for 循环。
  2. 以正确的顺序获取绘制的行...这意味着排序之后。
    我们需要使用row-selector 和有用的{ order: 'applied' } 技巧。
    dataTables forum question中找到
  3. 从中获取nodes
  4. 使用 jQuery .eq() 方法根据数组定位正确的行。
    所以我们必须先用行集合创建一个 jQuery 对象(用$() 包装)。
  5. 操作行!
    在我的示例中,我刚刚为子 td 添加了红色背景色。
    您将从这里做您的事情。

所以这里是整个函数:

"drawCallback": function(){
  var api = this.api();

  for(i=0;i<targets.length;i++){
    $(api.rows({ order: 'applied' }).nodes()).eq(targets[i]).find("td").addClass("red");
    console.log(targets[i]);
  }
}

CodePen


记住行是从零开始的...
注意上面操作的行索引是排序之后(因此它反映了顺序当前显示给用户的顺序,而不是从标记或 Ajax 提供给 Datatables 的顺序。)这意味着排序应与用户单击行时的排序相同(从而保存索引)。那可能是个问题... ;)

【讨论】:

  • 这很好,而且肯定是正确的,因为您已经设法基于数组定位行。您对数组“先前从用户行点击存储”的假设。是正确的。但是...我希望能够 open 行。我尝试修改您的代码,使其具有.addClass("red").open()(注意末尾的.open())但这似乎没有任何作用,行保持红色但它们没有扩展。
  • 在我的零配置示例中,没有什么可以“打开”。该示例是关于如何仅定位行。在您自己的 DataTable 中,尝试$(api.rows({ order: 'applied' }).nodes()).eq(targets[i]).addClass("shown red").child().show();。如果效果不错,只需从该行中删除红色类(仅用于测试);)
  • 感谢您的回答。我写了自己的答案,适用于我的应用程序。重要的是,答案要考虑到使用 ajax 源数据并扩展行而不是仅仅突出显示它。不过,您的回答是正确的。
【解决方案2】:

这个问题的答案是由一位同事提供的,并利用了 DataTables 提供的 rowCallback (https://datatables.net/reference/option/rowCallback) 回调。

var substancesTable = $('#substancesTable').DataTable({

// ...

"rowCallback": function(row) {
       var id = $(row).find('td:first').text();
       var index = $.inArray(id, openRows);

       if (index !== -1) {
           var tr = $(row).closest('tr');
           var row = substancesTable.row( tr );
           row.child( expand_substance(row.data()) ).show();
           tr.addClass('active');
       }
    }
});

此回调将后处理每一行(由row 表示)。行var index = $.inArray(id, openRows); 表示openRows 数组中的当前行(由来自var id 的文本标识)。由于我表中的第一列包含 ID,因此我们可以在 var idopenRows 之间进行匹配。

如果找到 ID,它将触发我编写的名为 expand_substance() 的函数。这和DataTables无关,是自定义的js函数。

在我的例子中,expand_substance() 函数负责进行 ajax 调用以获取更多详细信息,然后将这些详细信息填充到行中:

function expand_substance ( rowData ) {
    var div = $('<div/>')
        .text('Loading...');

    $.ajax( {
        url: '/view-substance/expand-substance/' + rowData.id,

        dataType: 'html',
        success: function ( data ) {
            div.html(data);
        }
    });

    return div;
}

这只是必需的,因为当用户在我的应用程序中展开一行时,显示的详细信息是通过 ajax 请求获得的。理论上expand_substance() 在页面加载时可能不会被使用。

这适用于我的应用程序。为这篇文章提供的另一个答案是正确的,但不使用 ajax 源数据,它不展开一行,而是用红色突出显示它。因此,我提供了自己的答案,因为这完全解决了这个问题,其他人可能会觉得它有用。

【讨论】:

    猜你喜欢
    • 2016-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多