首页 > 解决方案 > 如何使用 dom 在下载中包含 row().child 行:'Bfrtip' 使用 Datatables

问题描述

我正在使用这些dom: 'Bfrtip'按钮将复制和 Excel 按钮添加到我的数据表中。但是,我的 Datatable 还包含隐藏row().child的,当我单击按钮时不会被复制。如何使用复制功能包含子行?这是我正在使用的代码:

function format ( d ) {
    // `d` is the original data object for the row
    return '<table cellpadding="5" cellspacing="0" border="0" style="padding-left:30px;">'+
        '<tr>'+
            '<td>col5:</td>'+
            '<td style="word-break:break-all;">'+d.col5+'</td>'+
        '</tr>'+
    '</table>';
}

$(document).ready(function() {
    var table = $('#myDataBase').DataTable( {
              dom: 'Bfrtip',
        buttons: [
            'copyHtml5',
            'excelHtml5',
            'pageLength'
        ],
        "pagingType": "full_numbers",
        "iDisplayLength": 25,
        "ajax": "./myDataBase_objects.json",
        "columns": [
            {
                "className":      'details-control',
                "orderable":      false,
                "data":           null,
                "defaultContent": ''
            },
            { "data": "col1" },
            { "data": "col2" },
            { "data": "col3" },
            { "data": "col4" }
        ],
        "order": [[1, 'asc']]
    } );

源 json 如下,其中前 4 列显示在 DataTable 中,而 col5 没有:

{
    "data": [
        {
            "col1": "12",
            "col2": "98.2",
            "col3": "76",
            "col4": "376",
            "col5": "42,567"
        },
        {
            "col1": "11",
            "col2": "92.2",
            "col3": "70",
            "col4": "306",
            "col5": "22,567"
        },

    ]
}

标签: javascriptdatatables

解决方案


我的答案基于此处提供的演示,但使用了问题中的数据样本。

这是表格的样子,扩展了第一个子行,只是为了显示子级中的数据:

在此处输入图像描述

任何子行是否可见或隐藏都没有关系 - 复制/粘贴会抓取所有数据,不管怎样。

这是 DataTables 脚本 - 请注意,我正在硬编码此演示的数据,而不是使用带有 ajax 的 URL - 但这不会改变复制/粘贴方法:

<script type="text/javascript">

var dataSet = [
        {
            "col1": "12",
            "col2": "98.2",
            "col3": "76",
            "col4": "376",
            "col5": "42,567"
        },
        {
            "col1": "11",
            "col2": "92.2",
            "col3": "70",
            "col4": "306",
            "col5": "22,567"
        }

];

function format ( d ) {
    return '<table cellpadding="5"><tr><td>' + d.col5 + '</td></tr></table>';
}
 
$(document).ready(function() {
    var table = $('#example').DataTable( {
        dom: 'Bfrtip',
        data: dataSet,
        "columns": [
            {
                "className":      'details-control',
                "orderable":      false,
                "data":           null,
                "defaultContent": ''
            },
            { "data": "col1" },
            { "data": "col2" },
            { "data": "col3" },
            { "data": "col4" }
        ],
        "order": [[1, 'asc']],

    buttons: [
      {
        text: 'Custom Copy',
        action: function ( e, dt, node, config ) {
          // the column headings are here:
          var copyString = 'col1\tcol2\tcol3\tcol4\tcol5\n';

          table.rows().every( function () {
            // for each row, get the data items, separated by tabs:
            copyString = copyString + Object.values(this.data()).join('\t') + '\n';

          } );

          if (copyString !== undefined) {
            // create a textarea, write the data to it, then 
            // select it for copy/paste:
            var dummy = document.createElement("textarea");
            document.body.appendChild(dummy);
            dummy.setAttribute("id", "dummy_id");
            document.getElementById("dummy_id").value = copyString;
            dummy.select();
            document.execCommand("copy");
            document.body.removeChild(dummy);
          }

        }
      }
    ]

    } );
     
    // Add event listener for opening and closing details
    $('#example tbody').on('click', 'td.details-control', function () {
        var tr = $(this).closest('tr');
        var row = table.row( tr );
 
        if ( row.child.isShown() ) {
            // This row is already open - close it
            row.child.hide();
            tr.removeClass('shown');
        }
        else {
            // Open this row
            row.child( format(row.data()) ).show();
            tr.addClass('shown');
        }
    } );
} );

</script>

点击Custom Copy按钮的结果是剪贴板包含了所有表格的数据。

当粘贴到一个空的 Excel 工作表中时,它看起来像这样:

在此处输入图像描述

这是如何工作的:

因为所有数据项都在原始 JSON 对象中,所以每个表行都可以访问我们需要的所有数据,无论它是如何在主行和子行之间拆分的。

因此,按钮代码可以使用自定义函数来使用table.rows().every(...). 我们构建了一个包含所有这些数据的字符串 ( ),由制表符 ( ) 和换行符 ( )copyString分隔。\t\n

最后,我们创建一个新的临时 DOM 元素 -textarea我们将文本放入其中,以便我们可以将其复制到剪贴板。

这样做的一个缺点:没有关于复制/粘贴事件的通知给用户。如果您愿意,可以为此添加警报。

但好处是:这将找到所有数据,这与开箱即用的复制功能不同。


推荐阅读