[英]How to load the DataTable jQuery plugin when a Bootstrap modal window is completely loaded without getting asynchronous issues?
我目前正在使用 Bootstrap v4.4.1 和插件的 nodejs 引导版本:
require('datatables.net-bs4')(window, $);
require('datatables.net-colreorder-bs4')(window, $);
require('datatables.net-fixedheader-bs4')(window, $);
首先,我加载 Bootstrap 模态 window 的 html 内的表中的所有行。 所有这些操作都是同步的,所以我在这里看不到任何问题。 每一个函数get_*
只是用 jQuery 添加节点元素。
for (var i = 0; i < cols.length; i++) {
var col_name = cols[i];
var name = self.get_col_name(col_name);
var data_type = self.get_data_type(col_name)
var attrs = self.pj_cols[col_name]['attrs'].join(', '); // TODO: translate to icons or extract just some of them?
var cb_export = self.get_cb_export(i, col_name);
var sel_cur_prec = self.get_cur_prec(col_name);
var txt_cur_unit = self.get_txt_cur_unit(col_name);
var set_bt = self.get_set_bt(col_name, i);
var tr = $('<tr>');
tr.append(
$('<td>', {html: cb_export }),
name,
$('<td>', {html: data_type }),
$('<td>', {text: attrs }),
$('<td>', {html: sel_cur_prec }),
$('<td>', {html: txt_cur_unit }),
$('<td>', {html: set_bt })
);
$('#table_column_project tbody').append(tr);
}
然后我通过单击按钮以编程方式加载模态 window 以触发并显示它
$('#modal_column_project').click();
最后我运行DataTable()
function 以便将表格转换为 DataTable
$('#column_project_win').on('shown.bs.modal', function (e) {
$('#table_column_project').DataTable( {
scrollY: 400,
scrollCollapse: true,
paging: false,
searching: true,
ordering: true,
order: [[ 1, 'asc' ]],
info: false,
columnDefs: [
{ targets: '_all', visible: true, },
{ targets: [6], orderable: false, searchable: false, },
{ targets: [0, 2, 4, 5, 6], type: 'html'}
],
initComplete: function () {
// initially the div which is a containter has opacity 0
$('#div_column_project').animate({ opacity: 1, }, { duration: 100, });
},
});
});
这有时运作良好。 通常,这些行永远不会出现,DataTable 会显示以下消息:
No matching records found
为了避免这个异步问题,有没有办法更好地做到这一点? 我说异步是因为显然是随机的。
我还尝试添加此 hack,但效果不佳。 我认为问题出在删除表行的 DataTable 调用中
var _check_loaded_rows = setInterval(function() {
if ($('#table_column_project tbody tr').length == cols.length) { // check if all rows are correctly loaded
clearInterval(_check_loaded_rows);
$('#table_column_project').DataTable( { // TODO: show only when rendered
scrollY: 400,
scrollCollapse: true,
paging: false,
searching: true,
ordering: true,
order: [[ 1, 'asc' ]], // this is the value by default
info: false,
columnDefs: [
{ targets: '_all', visible: true, },
{ targets: [6], orderable: false, searchable: false, },
{ targets: [0, 2, 4, 5, 6], type: 'html'}
],
initComplete: function () {
$('#div_column_project').animate({ opacity: 1, }, { duration: 100, });
},
});
}
}, 100);
实际上,现在我有一个延迟 500 毫秒的setTimeout
以使其正常工作。
我也读过这个答案,海报建议我们应该使用引导版本,表应该被初始化(我使用opacity
来隐藏它,而不是display: none;
)并显示 DataTable 我使用内置方法initComplete
来运行指令来设置不透明度。
如果您只有几百行,为什么不使用initComplete
中的 API 插入它们呢? 您可以将 API 传递给另一个 function (就像使用您已经用来填充的get_*
方法一样(不清楚它是否是 function):
function populate(api) {
for (var i = 0; i < cols.length; i++) {
...
api.row.add([cb_export, name, data_type, attrs, sel_cur_prec, txt_cur_unit, set_bt])
}
api.draw/()
}
$('#table_column_project').DataTable({
...
initComplete: function() {
const api = this.api()
populate(api)
}
})
或者,您可以使用 promise 并在模式事件处理程序中等待:
function populate() {
return new Promise(resolve => {
...
if (i+1 === cols.length) resolve()
})
}
$('#column_project_win').on('shown.bs.modal', function (e) {
populate().then(() => {
$('#table_column_project').DataTable( {
...
})
})
})
如果您的 nodejs(旧版本)中没有 Promise 可用,您可以使用例如es6-promise
和
const Promise = require('es6-promise').Promise
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.