我正在使用一个使用DataTables生成HTML表的应用程序,该表由来自ajax请求的数据填充。
这很简单:
var substancesTable = $('#substancesTable').DataTable({
"processing": true,
"serverSide": true,
"searching": false,
"ajax": {
"url": "/get-substances.json",
"method": "POST",
"cache": false,
"dataSrc": function (json) {
// Update non-Datatables UI elements and perform other functions based on the ajax response
$('#numSubstances').html(json.recordsTotal);
drawOptionsButton(json.isFiltering);
// Must return data for DataTables to work
return json.data;
}
},
// ...
});
DataTables提供了一个称为rowCallback
(https://datatables.net/reference/option/rowCallback)的回调,该回调允许在绘制表后 对表行进行后处理。这里的关键是,它是对/get-substances.json
的ajax请求的之后;该表必须填充有数据,因为此时该回调用于处理表中的数据。
在rowCallback
中,我在表中提供了行ID的数组-也就是说,该ID与<tr>
中的#substancesTable
元素相对应-然后继续扩展这些行行。我可以通过对行ID的数组进行硬编码来手动完成此操作,例如
var substancesTable = $('#substancesTable').DataTable({
// ...
"rowCallback": function(row) {
var id = $(row).find('td:first').text();
var index = $.inArray(id, ['4', '7']); // hardcoded array
if (index !== -1) {
var tr = $(row).closest('tr');
var row = substancesTable.row( tr );
row.child.show();
tr.addClass('active');
}
});
我已硬编码的数组表示在填充表后 将第4行和第7行展开,这等效于用户单击它们。
我遇到的问题是我不想对数组进行硬编码。该应用程序将等价var index
存储在Redis(缓存)中,这意味着即使用户离开页面,我们也可以轻松地获取数据。因此,我添加了第二个ajax请求(在var substancesTable...
块之外)以获取Redis数据。这会发出ajax请求以填充数组activeRows
:
var activeRows = [];
$.ajax({
url: '/view-substance/get-active-rows',
method: 'post',
cache: false,
}).done(function(data) {
activeRows = data;
console.log(activeRows);
});
我了解ajax的本质意味着我的代码是异步的。在某些情况下,上面显示的ajax请求将在绘制DataTable之前完成,因此我得到console.log(activeRows)在呈现表之前出现,而在其他情况下,它随后发生。
发出第二个Ajax请求,以便可以使用其中的值代替硬编码数组的正确方法是什么?非常感谢,我需要将响应转换为数组(因为console.log
语句中的响应仍然是JSON)。但是我的问题集中在将代码放在哪里,以便可以在rowCallback
内可靠地使用它?
我已阅读How do I return the response from an asynchronous call?并了解异步性质。我不知道如何构造它以便在已经是ajax请求的一部分的回调中使用。
任何建议将不胜感激。
该应用程序使用DataTables版本1.10.16和jquery 3.2.1
答案 0 :(得分:3)
您实际上可以使用ajax
选项执行以下操作:
发出第一个AJAX请求,以检索活动行。
一旦检索到活动行,请进行第二个AJAX请求,以检索表数据。
示例:(请参阅完整的代码和演示here)
var activeRows = [];
function getActiveRows() {
return $.ajax({
url: '/view-substance/get-active-rows',
type: 'POST',
dataType: 'json'
...
}).done(function(data){
activeRows = data;
console.log(activeRows);
});
}
function getTableData(data, callback) {
return $.ajax({
url: '/get-substances.json',
type: 'POST',
dataType: 'json',
'data': data // must send the `data`, but can be extended using $.extend()
...
}).done(callback); // and call callback() once we've retrieved the table data
}
$('#example').dataTable({
ajax: function(data, callback){
getActiveRows().always(function(){
getTableData(data, callback);
});
},
rowCallback: function(row, data){
...
}
});
在上面的示例中,我将AJAX调用分为两个不同的函数,主要是为了避免在调用ajax
时在$('#example').dataTable()
选项中出现长时间缩进。否则代码将如下所示:
var activeRows = [];
$('#example').dataTable({
ajax: function(data, callback){
// 1. Retrieve the active rows.
$.ajax({
url: '/view-substance/get-active-rows',
type: 'POST',
dataType: 'json'
...
}).done(function(res){
activeRows = res;
console.log(activeRows);
}).always(function(){
// 2. Retrieve the table data.
$.ajax({
url: '/get-substances.json',
type: 'POST',
dataType: 'json',
'data': data // must send the `data`, but can be extended using $.extend()
...
}).done(callback); // and call callback() once we've retrieved the table data
});
},
rowCallback: function(row, data){
...
}
});
我使用了.always()
,以便在检索活动行失败的情况下仍可以检索表数据。
答案 1 :(得分:1)
您可以通过Promises解决您的问题。承诺是帮助您管理和协调异步任务的对象。您的情况如下:
var activeRows = [];
var substancesTable = $('#substancesTable').DataTable({
// ...
});
var pDataTable = new Promise(function(resolve, reject){
// you wan't to resolve just once,
// after the table has finished processing the received data.
// (You may want to change draw to an event that's more suitable)
substancesTable.one('draw', resolve);
});
var pOpenRows = new Promise(function( resolve, reject ){
$.ajax({
url: '/view-substance/get-active-rows',
method: 'post',
cache: false,
}).done(function(data) {
// you can either save your rows globaly or give them to the resolve function
// you don't have to do both
activeRows = data;
resolve( data );
});
});
// Here we basically create a third promise, which resolves (or rejects)
// automatically based on the promises in the array.
Promise.all([pDataTable, pOpenRows])
.then(function( values ){
// expand your table rows here
// Note: if you gave your rows to the resolve function you can access
// them here in values[1] (pDataTable's data would be in values[0])
});
如果您想进一步了解Promises:
有关浏览器支持的详细信息,您可以在这里查看: