【问题标题】:Why doesn't columns.render execute when DataTable().draw() is called?为什么调用 DataTable().draw() 时不执行 columns.render?
【发布时间】:2014-09-18 21:01:30
【问题描述】:

我很困惑为什么columns.render 不包含在DataTable().draw() 的执行管道中。

一个例子:

HTML

<table id="data">
    <thead>
        <tr>
            <th>TimeColumn</th>
            <th>Column 2</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>123</td>
            <td>234</td>
        </tr>
        <tr>
            <td>345</td>
            <td>456</td>
        </tr>
        <tr>
            <td>567</td>
            <td>678</td>
        </tr>
    </tbody>
</table>

<button id="refresh">Refreh</button>

jQuery

$(document).ready(function () {
    $('#data').DataTable({
        columnDefs: [{
            targets: 0,
            render: function(data, type, row, meta) {
                return data + ' time:' + Date.now();
            }
        }]
    });

    $('#refresh').on('click', function() {
        $('#data').DataTable().draw();
    });
});

单击Refresh 按钮时的预期结果是时间值应该在第一列中前进,但事实并非如此。
初始化后永远不会调用分配的渲染函数。

(示例的jsFiddle。)

有什么解决方法还是我必须深入研究DataTables的代码?

【问题讨论】:

    标签: jquery html jquery-datatables


    【解决方案1】:

    我最终修改了jquery.datatables.js 版本1.10.2,而不是销毁数据表并重新填充它。

    主要问题是jquery.datatables.js 中的第 1935 行检查该行是否已创建:

    if ( aoData.nTr === null )
    {
      _fnCreateTr(oSettings, iDataIndex);
    }
    

    解决此问题的一种方法是设置aoData.nTr = null。但这可能会破坏其他功能或导致不必要的副作用,因此这不是一个可接受的解决方案。

    我选择向 .draw() 函数添加一个参数(第 7137 行)并添加一个名为 bForceReDraw 的设置(draw() 已经接受了一个参数,因此我们添加了第二个参数):

    _api_register('draw()', function (resetPaging, forceReDraw) {
      return this.iterator( 'table', function ( settings ) {
        settings.bForceReDraw = forceReDraw === true;
          _fnReDraw(settings, resetPaging === false);
      } );
    } );
    

    然后我将第 1935 行的 null 检查更改为:

    if ( aoData.nTr === null || oSettings.bForceReDraw === true )
    {
      _fnCreateTr(oSettings, iDataIndex);
    }
    

    在函数_fnCreateTr() 中还有一个null 检查nTr(第1586 行),所以我也需要修改它:

    if ( row.nTr === null || oSettings.bForceReDraw === true )
    {
      nTr = nTrIn || document.createElement('tr');
      ...
    

    现在我们只需使用新参数调用draw(),一切都按预期工作。

    $('#data').DataTable().columns.adjust().draw(false, true);
    

    【讨论】:

    • 我并不热衷于修改源代码本身来解决问题。我会说它造成伤害的机会大于好处。
    • 这是你的特权。修改应该完全没有副作用,因为我添加了一个在其他任何地方都没有引用的设置。仅当使用true 作为第二个参数显式调用draw() 时,才会重新呈现该行。否则执行默认行为。
    • 同意@SaniHuttunen,就像大多数其他jQuery插件一样,每个版本的dataTables都有错误和失误,就像这种情况一样,dataTables作为一个整体并不能满足每个程序员的需求。 1)寻找“本机”解决方案 2)寻找解决方法 3)自己实现所需的功能。为一份好工作 +1。
    • 哇,很高兴你找到了这个。可以想象,这只是为我节省了几个小时。而且 - 大约一年后 - 该错误仍然存​​在。猜猜这一定意味着这种用例非常罕见。
    • @Sani:不过对我来说效果很好。但是我使用 JS 数组作为数据源,而不是像你一样的表格内容。也许这会有所作为。
    【解决方案2】:

    每个人在动态重新加载数据表时都会遇到问题。 考虑这种方法。先销毁DataTable重新渲染。

    var dataSet = [];
    
    if ($.fn.dataTable.isDataTable('#yourTable')) {
        $('#yourTable').DataTable({
            "destroy": true,
            "processing": true,
            "data": dataSet
        });
    } else {
        $('#yourTable').DataTable({
            "processing": true,
            "data": dataSet
        });
    }
    

    【讨论】:

    • 不热衷于破坏 DataTable 并重新填充它。最终改为修改 datatables.js 源。
    • @SaniHuttunen,请将您的解决方案发布为已接受的答案。也许它会在未来帮助其他人。
    【解决方案3】:

    我发现,与.draw() 相反,.columns.adjust().draw(); 会再次触发render 函数。但是,不幸的是,它不会重新渲染表格......(?)

    我发现的唯一解决方法是.destroy() 表,将$('#data').html() 替换为其原始内容,然后从$('#data').DataTable({ columnDefs: colDefs }); 重新开始。

    $(document).ready(function () {
        var table_data = $('#data').html();
    
        var colRender = function (data, type, row, meta) {
            var today = new Date();
            var ms = today.getMilliseconds();
            var ss = today.getSeconds();
            var mn = today.getMinutes();
            var hh = today.getHours();
            var time = ' time:' + hh + ':' + mn + ':' + ss + ':' + ms
            console.log('data+time', data + time);
            return data + time;
        }
    
        var colDefs = [{
            targets: 0,
            render: colRender
        }];
        
        $('#data').DataTable({
            columnDefs: colDefs
        });
    
        $('#refresh').click(function () {
            // $('#data').DataTable().columns.adjust().draw();
            // $('#data').DataTable().draw();
            $('#data').DataTable().destroy();
            $('#data').html(table_data);
            $('#data').DataTable({
                columnDefs: colDefs
            });
        });
    });
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="http://cdn.datatables.net/1.10.2/js/jquery.dataTables.min.js"></script>
    <link href="http://cdn.datatables.net/1.10.2/css/jquery.dataTables.min.css" rel="stylesheet"/>
    <table id="data">
        <thead>
            <tr>
                <th>TimeColumn</th>
                <th>Column 2</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>123</td>
                <td>234</td>
            </tr>
            <tr>
                <td>345</td>
                <td>456</td>
            </tr>
            <tr>
                <td>567</td>
                <td>678</td>
            </tr>
        </tbody>
    </table>
    <button id="refresh">Refresh</button>

    【讨论】:

    • 是的,我注意到.columns.adjust() 也将执行渲染,但正如您所说,它不会绘制新值。我不热衷于破坏 DataTable 并重新填充它。最终改为修改 datatables.js 源。主要问题是DataTable.models.oSettings.nTr 是在初始化时设置的,并且在重绘表格时它检查(1.10.2 中的第 1935 行)它是否为空。如果为空,则创建行,否则使用旧值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多