【问题标题】:How to load the DataTable jQuery plugin when a Bootstrap modal window is completely loaded without getting asynchronous issues?当 Bootstrap 模式窗口完全加载而没有出现异步问题时,如何加载 DataTable jQuery 插件?
【发布时间】:2020-10-07 16:35:08
【问题描述】:

我目前正在使用 Bootstrap v4.4.1 和插件的 nodejs 引导版本:

require('datatables.net-bs4')(window, $);
require('datatables.net-colreorder-bs4')(window, $);
require('datatables.net-fixedheader-bs4')(window, $);

首先,我加载表中的所有行,该表位于 Bootstrap 模式窗口的 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);
}

然后我通过单击按钮以编程方式加载模式窗口并显示它

$('#modal_column_project').click();

最后我运行 DataTable() 函数来转换 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);

实际上,我现在有一个 setTimeout 延迟 500 毫秒,以使其正常工作。

我还阅读了this answer,其中海报建议我们应该使用引导版本,表应该被初始化(我使用opacity 隐藏它,而不是display: none;)并显示我使用的DataTable内置方法initComplete 运行指令设置不透明度。

【问题讨论】:

    标签: javascript jquery twitter-bootstrap datatable bootstrap-modal


    【解决方案1】:

    如果您只有几百行,为什么不使用initComplete 中的 API 插入它们呢?您可以将 API 传递给另一个函数(例如使用您已经用来填充的 get_* 方法的函数(不清楚它是否是函数)):

    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)
      }
    })
    

    或者,您可以使用承诺并在模式事件处理程序中等待:

    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  
    

    【讨论】:

    • 谢谢 我喜欢在initComplete 中添加元素的解决方案。由于某些元素是 html 代码,我必须使用 sel_cur_prec.prop('outerHTML') 添加它们
    • 很遗憾我仍然遇到同样的问题,initComplete 函数可能有问题,我不知道
    • 嘿@ChesuCR 你能设置一个小提琴来复制问题吗?
    • 这里是一个起点-> jsfiddle.net/0f9Ljfjr
    • @ChesuCR,我回家就做!
    猜你喜欢
    • 1970-01-01
    • 2011-10-23
    • 2018-01-24
    • 2011-09-19
    • 1970-01-01
    • 2010-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多