7

我正在尝试创建一个表格,当单击加号图像时可以看到更多详细信息 - 类似于DataTables 隐藏行详细信息示例

不幸的是,有一个警告被打印为 JavaScript 警报,并且表格标题也放错了位置 - 好像其中的表格单元格太多或不够:

在此处输入图像描述

我准备了一个简单的测试用例,当您将其保存到文件并在浏览器中打开时,它会立即运行:

<!DOCTYPE HTML>
<html>
<head>
    <link type="text/css" rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1/themes/redmond/jquery-ui.css">
    <link type="text/css" rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/css/jquery.dataTables_themeroller.css">
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.min.js"></script>
    <script type="text/javascript" src="https://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/jquery.dataTables.min.js"></script>
    <script type="text/javascript">

        var data = [
            {"Total":17,"A":0,"B":0,"Details":{"BSN":"1147387861","ProjectName":"R127","StationName":"D"},"C":0,"D":17,"Test":"GSM_1900_GMSK_TXPOWER_HP_H","Measurement":"MEASUREMENT"},
            {"Total":8,"A":0,"B":0,"Details":{"BSN":"1147387861","ProjectName":"R127","StationName":"D"},"C":0,"D":8,"Test":"TX_PWR_64_54","Measurement":"POWER"}
        ];

        $(function() {

            function fnFormatDetails(oTable, nTr) {
                var aData = oTable.fnGetData(nTr);
                var sOut = '<table bgcolor="yellow" cellpadding="8" border="0" style="padding-left:50px;">';
                sOut += '<tr><td>BSN:</td><td>' + aData['Details']['BSN'] + '</td></tr>';
                sOut += '<tr><td>Station:</td><td>' + aData['Details']['StationName'] + '</td></tr>';
                sOut += '<tr><td>Project:</td><td>' + aData['Details']['ProjectName'] + '</td></tr>';
                sOut += '</table>';

                return sOut;
            }

            var fails = $('#fails').dataTable({
                bJQueryUI: true,
                sPaginationType: 'full_numbers',
                aaData: data,
                aaSorting: [[2, 'desc']],
                aoColumns: [
                    { mDataProp: 'Test',        bSearchable: true,  bSortable: true },
                    { mDataProp: 'Measurement', bSearchable: true,  bSortable: true },
                    { mDataProp: 'Total',       bSearchable: false, bSortable: true },
                    { mDataProp: 'A',           bSearchable: false, bSortable: true },
                    { mDataProp: 'B',           bSearchable: false, bSortable: true },
                    { mDataProp: 'C',           bSearchable: false, bSortable: true },
                    { mDataProp: 'D',           bSearchable: false, bSortable: true },
                ]
            });

            var th = document.createElement('th');
            var td = document.createElement('td');
            td.innerHTML = '<img src="http://www.datatables.net/release-datatables/examples/examples_support/details_open.png" class="details">';

            $('#fails tbody th').each(function() {
                this.insertBefore(th, this.childNodes[0]);
            });

            $('#fails tbody tr').each(function() {
                this.insertBefore(td.cloneNode(true), this.childNodes[0]);
            });

            $('#fails tbody').on('click', 'td img.details', function() {
                var nTr = $(this).parents('tr')[0];
                if (fails.fnIsOpen(nTr)) {
                    this.src = 'http://www.datatables.net/release-datatables/examples/examples_support/details_open.png';
                    fails.fnClose(nTr);
                } else {
                    this.src = 'http://www.datatables.net/release-datatables/examples/examples_support/details_close.png';
                    fails.fnOpen(nTr, fnFormatDetails(fails, nTr), 'details');
                }
            });
        });

    </script>
</head>
<body>

<table id="fails" cellspacing="0" cellpadding="4" width="100%">
    <thead>
    <tr>
        <th>Test</th>
        <th>Measurement</th>
        <th>Total</th>
        <th>A</th>
        <th>B</th>
        <th>C</th>
        <th>D</th>
    </tr>
    </thead>
    <tbody>
    </tbody>
</table>

</body>
</html>

有没有人有想法,如何解决这个问题?

我尝试<th>Details</th>在 HTML 正文中添加/删除,但没有帮助。

我也在DataTables 论坛上问过这个问题。

更新:

我收到了 DataTables 作者的有用评论,并决定只在每一行的第一个单元格的内容前面加上加号图像 - 而不是在每一行中添加一个新单元格。

不幸的是,我遇到了一个新问题:显示了加号图像,但原始文本(测试名称)消失了:

在此处输入图像描述

这是我的新代码(加号前面是propTest):

<!DOCTYPE HTML>
<html>
<head>
    <link type="text/css" rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1/themes/redmond/jquery-ui.css">
    <link type="text/css" rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/css/jquery.dataTables_themeroller.css">
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.min.js"></script>
    <script type="text/javascript" src="https://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/jquery.dataTables.min.js"></script>
    <script type="text/javascript">

        var data = [
            {"Total":17,"A":0,"B":0,"Details":{"BSN":"1147387861","ProjectName":"R127","StationName":"D"},"C":0,"D":17,"Test":"GSM_1900_GMSK_TXPOWER_HP_H","Measurement":"MEASUREMENT"},
            {"Total":8,"A":0,"B":0,"Details":{"BSN":"1147387861","ProjectName":"R127","StationName":"D"},"C":0,"D":8,"Test":"TX_PWR_64_54","Measurement":"POWER"}
        ];

        function propTest(data, type, val) {
            if (type === 'set') {
                console.log(val); // for some reason prints "null"
                data.name = val;
                data.display = '<img src="http://www.datatables.net/release-datatables/examples/examples_support/details_open.png" width="20" height="20" class="details"> ' + val;
                return;
            }

            if (type === 'display') {
                return data.display;
            }

            // 'sort', 'type', 'filter' and undefined
            return data.name;
        }

        $(function() {

            function fnFormatDetails(oTable, nTr) {
                var aData = oTable.fnGetData(nTr);
                var sOut = '<table bgcolor="yellow" cellpadding="8" border="0" style="padding-left:50px;">';
                sOut += '<tr><td>BSN:</td><td>' + aData['Details']['BSN'] + '</td></tr>';
                sOut += '<tr><td>Station:</td><td>' + aData['Details']['StationName'] + '</td></tr>';
                sOut += '<tr><td>Project:</td><td>' + aData['Details']['ProjectName'] + '</td></tr>';
                sOut += '</table>';

                return sOut;
            }

            var fails = $('#fails').dataTable({
                bJQueryUI: true,
                sPaginationType: 'full_numbers',
                aaData: data,
                aaSorting: [[2, 'desc']],
                aoColumns: [
                    { mData: propTest,      bSearchable: true,  bSortable: true },
                    { mData: 'Measurement', bSearchable: true,  bSortable: true },
                    { mData: 'Total',       bSearchable: false, bSortable: true },
                    { mData: 'A',           bSearchable: false, bSortable: true },
                    { mData: 'B',           bSearchable: false, bSortable: true },
                    { mData: 'C',           bSearchable: false, bSortable: true },
                    { mData: 'D',           bSearchable: false, bSortable: true }
                ]
            });

            $('#fails tbody').on('click', 'td img.details', function() {
                var nTr = $(this).parents('tr')[0];
                if (fails.fnIsOpen(nTr)) {
                    this.src = 'http://www.datatables.net/release-datatables/examples/examples_support/details_open.png';
                    fails.fnClose(nTr);
                } else {
                    this.src = 'http://www.datatables.net/release-datatables/examples/examples_support/details_close.png';
                    fails.fnOpen(nTr, fnFormatDetails(fails, nTr), 'details');
                }
            });
        });

    </script>
</head>
<body>

<table id="fails" cellspacing="0" cellpadding="4" width="100%">
    <thead>
    <tr>
        <th>Test</th>
        <th>Measurement</th>
        <th>Total</th>
        <th>A</th>
        <th>B</th>
        <th>C</th>
        <th>D</th>
    </tr>
    </thead>
    <tbody>
    </tbody>
</table>

</body>
</html>
4

1 回答 1

9

有几种方法可以使用 DataTables (DT) 实现这种类型的行为。您可以实现最初的目标,也可以对扩展器和Test数据使用同一列。

我正在花时间展示几个选项,因为我希望这可以作为其他人要求做类似事情的参考。

对于以下所有内容,您的表应在创建 DT 之前包含所有所需的列(静态或动态)。


单独列中的扩展器

使用默认内容属性:

这是需要对现有示例进行最少修改的选项,并且可能是最简单的选项。只需sDefaultContent为您的额外列添加一个选项:

{
    mData: null,
    bSearchable: false,
    bSortable: false,
    sDefaultContent: '<div class="expand /">',
    sWidth: "30px"
},

mData属性设置为null,因为它的内容与行的数据数组无关。这使得 DT 使用sDefaultContent.

我冒昧地将 CSS 用于展开器按钮,因为这使示例更简单,也使行为和表示分离。

我使用的 CSS:

tr div.expand {
  width: 20px;
  height: 20px;
  background-image: url('http://www.datatables.net/release-datatables/examples/examples_support/details_open.png');
}

tr div.open {
  background-image: url('http://www.datatables.net/release-datatables/examples/examples_support/details_close.png');  
}

和扩展功能:

$('#fails tbody').on('click', 'td div.expand', function () {
    var nTr = $(this).parents('tr')[0];
    if (fails.fnIsOpen(nTr)) {
        $(this).removeClass('open');
        fails.fnClose(nTr);
    } else {$.fn.dataTableExt.sErrMode = 'throw' ;
        $(this).addClass('open');
        fails.fnOpen(nTr, fnFormatDetails(fails, nTr), 'details');
    }
});

我们div以一个expand类为目标,并根据需要切换其open类。

单独展开列

JSBin示例


第一列中包含的扩展器

使用格式化程序:

你可以指定一个aoColumnDefsconfig数组,它比aoColumnsconfig更强大、更灵活。

为该列指定渲染器函数是通过mRenderconfig 属性完成的。

相关列的设置:

aoColumnDefs: [{
    aTargets: [0],
    mData: 'Test',
    bSearchable: true,
    bSortable: true,
    mRender: expandRenderer
},
 ...
]

该函数在不同的上下文中被多次调用,应该告诉 DT 如何在表本身中显示数据,以及帮助确定用于排序和过滤目的的数据类型。

渲染器:

function expandRenderer(data, type, full) {
    switch (type) {
        case 'display':
          return '<div class="expand-wrapper">'+
            '<span class="expand"></span>'+
            '<span class="data">'+
              data+
            '</span></div>';
        case 'type':
        case 'filter':
        case 'sort':
            return data;
    }
}

它需要 3 个参数:

  • data:来自行数组的数据,在这种情况下,是存储在Test.
  • type: 请求的类型。它表示 DT 期望返回的内容:
    • 'display':将在单元格本身中显示什么。
    • 'type':从函数返回的内容将用于确定行的数据类型。
    • 'filter', 'sort': 用于表格过滤(搜索)和排序的数据。
  • full:该行的完整数据。

这一次,我决定使用span由 s 包裹的 s div。为了使图标垂直居中并使表格保持在一行中,我使用了以下 CSS:

tr span.expand {
    width: 20px;
    height: 20px;
    background-image: url('http://.../details_open.png');
    display:inline-block;
    vertical-align: middle;
    margin-right: 5px;
}

div.expand-wrapper {
    white-space:nowrap;
}

vertical-align: middle这里按预期工作,因为这是一个inline显示(inline-block特别是)。

如果没有这个 CSS,DT 将无法优雅地处理列宽,因为第一列并不真正意识到扩展器占用的额外空间。

没有这个 CSS: 同一列中的扩展器

使用这个 CSS:

同一列和同一行中的扩展器

以及对应的JSBin 例子

提示:

我不喜欢使用alert()来显示错误。对于 DT,您可以通过更改其错误模式设置来更改此行为:

$.fn.dataTableExt.sErrMode = 'throw' ;

这将引发异常,因此您可以使用控制台即时捕获它,或者如果未捕获则将其记录下来。

资源:

DataTable 列选项

DataTable 选项快速参考


PS,

可以通过将函数作为mData配置参数传递来进行进一步的自定义,但这超出了此答案的范围。

于 2013-09-13T13:37:56.107 回答