通过 Ajax 加载行详细信息
展示有关 DataTable 中某行的详细信息是一项热门功能。它允许最终用户以可访问的方式轻松处理主表格视图,同时还可让他们以结构化的方式深入查询更详细的数据。
DataTables 提供子行 API 方法 (row().child()
、row().child().show()
等),让你可以轻松显示类似的详细行。此网站上甚至还有一个简单示例。
此博文的主题是建立在该示例的基础之上,说明如何处理一个简单但通常请求的扩展:通过 Ajax 方式异步加载子行数据,而不是仅仅使用表中的已有数据。
示例
下表显示了我们将在此文中构建的一个示例。单击显示图标将显示“正在加载”消息,然后此消息会被从服务器 Ajax 加载的数据替换掉。在此演示中,已将服务器端脚本中添加了两秒的人为延迟,这样你就可以看到加载消息,然后看到该消息被加载的信息所替换掉。
姓名 | 职位 | 办公室 | 工资 | |
---|---|---|---|---|
姓名 | 职位 | 办公室 | 工资 |
设置
此博文的大部分内容实际上是有关 DataTable 的基本设置,因为其最终实现可能出乎意料地简单。如果你已经熟练创建 DataTable,请跳到“Ajax 请求”部分。
基本 DataTable
让我们从头开始,创建一个使用通过 Ajax 获取数据且使用对象作为数据源的 DataTable
var table = $('#myTable').DataTable( {
ajax: '/api/staff',
columns: [
{
className: 'details-control',
orderable: false,
data: null,
defaultContent: ''
},
{ data: "name" },
{ data: "position" },
{ data: "office" },
{ data: "salary" }
],
order: [[1, 'asc']]
} );
请注意,表中的第一列有为其分配一个类,并且仅仅显示一个空字符串(即无内容!)作为其数据值。这样做是为了能够将该单元格用作打开/关闭图标,让最终用户单击该图标以显示详细行。
事件处理程序
我们可以附加以下事件侦听器来执行打开/关闭操作
$('#myTable tbody').on('click', 'td.details-control', function () {
var tr = $(this).closest('tr');
var row = table.row( tr );
if ( row.child.isShown() ) {
row.child.hide();
tr.removeClass('shown');
}
else {
row.child( format(row.data()) ).show();
tr.addClass('shown');
}
} );
在上述代码中,我们使用row().child.isShown()
来检查行是否有已显示的子行。如果有,则使用row().child.hide()
将其隐藏;如果还没有,则使用row().child().show()
来创建该子行。
整篇文章的主旨围绕着后者的这一功能!最简单的情况下,你可以给 row().child()
传递一个字符串,它会在子行中显示该字符串,但更重要的是,你还可以传入一个节点(或包含一个节点的 jQuery 对象),该节点将在表格中显示。这样一来,只要我们保留对该节点的引用,就可以在 Ajax 请求完成后,非常方便地更新文档。
Ajax 请求
我们的目标是创建一个 Ajax 请求,其响应将决定在详细信息行中显示的内容。当数据正在加载时,我们要向最终用户显示“Loading”消息,以便他们知道正在发生某些事情。我们可以利用 JavaScript 中一项非常强大的功能来实现,作为 JavaScript 开发人员,我们经常使用这项功能,但并不总是给它起个名称:闭包。
你会注意到,在第 10 行事件处理程序代码中,我们调用了一个名为 format
的自定义函数(使用任何你想要的函数名!)并将行数据传递进去 - 我们想做的是,让它向 DataTables 返回带有加载消息的元素,以便它能立即显示,同时创建一个 Ajax 请求,在数据加载后更新该元素。
function format ( rowData ) {
var div = $('<div/>')
.addClass( 'loading' )
.text( 'Loading...' );
$.ajax( {
url: '/api/staff/details',
data: {
name: rowData.name
},
dataType: 'json',
success: function ( json ) {
div
.html( json.html )
.removeClass( 'loading' );
}
} );
return div;
}
基本上就是这样!在子行中显示什么内容完全取决于你,因为它只是一个 div
容器元素。你可以使用动画显示它,插入另一个 DataTable,随你便!此处的关键是将 div
返回给子行进行呈现,同时利用 Ajax 和闭包来异步填充该 div
。