DataTables搜索子行内容

16
数据表的搜索栏无法搜索子行中的内容。

我已经广泛搜索了解这个问题的答案(1, 2, 3, 4, 5, 6, 7, 8, 9),但对这个问题几乎没有任何回应。

这里有一个简单的 jsfiddleDataTables debugger results

我想在表格中搜索分机号(在子行中),但是在搜索栏中输入一个分机号并没有搜索到结果。

我尝试了this post 中提供的解决方法,添加了以下内容:

table.columns().every( function () {
    var that = this;
    var header = this.header();

    $( 'input', this.footer() ).on( 'keyup change', function () {
        that
        .column( header.getAttribute('data-search-index')*1 ) // *1 to make it a number
        .search( this.value )
        .draw();
    } );
} );

...但是它仍然无法正常工作,正如您可以在上面链接的jsfiddle中看到的那样。

有人能帮我吗?

谢谢

4个回答

18

解决方案

为了让jQuery DataTables搜索子行,您需要将子行中显示的数据添加为隐藏列到主表中。

例如,您可以使用columns.visible选项为extn数据属性添加隐藏列,如下所示:

JavaScript:

    "columns": [
        {
            "class":          'details-control',
            "orderable":      false,
            "data":           null,
            "defaultContent": ''
        },
        { "data": "name" },
        { "data": "position" },
        { "data": "office" },
        { "data": "salary" },
        { "data": "extn", "visible": false }            
    ],

HTML:

<thead>
    <tr>
        <th></th>
        <th>Name</th>
        <th>Position</th>
        <th>Office</th>
        <th>Salary</th>
        <th>Extn.</th>
    </tr>
</thead>

演示

请查看此jsFiddle以获取代码和演示。搜索 5407,即使数据仅出现在子行中,第一行也将显示。


3
这是我所见过的更好的解决方案,而且不需要任何额外的代码。清晰简单。感谢分享! - user3436467
2
这真的很有用,但是当搜索数据仅出现在子级中时,我该如何显示子行和父行呢?如果搜索数据仅出现在父级中,则应保持子级隐藏,仅显示父级。 - Cristina Fierbinteanu

3

我必须问一下:是什么让您相信只有在显示子行时才能在动态注入的子行内容中搜索?而 column() 搜索又如何能够涵盖其他行的内容呢?

当然,有一个解决方法。可以将子行内容保存在数组中,而不是反复创建 :

var details = [];

现在,当您初始化表时,也要初始化子行内容:
...
columns: [{
   className: 'details-control',
   orderable: false,
   data: null,
   defaultContent: '',
   render: function(data, type, row, meta) {  
      details[meta.row] = format(data);
   }    
}, 
...

在format()函数中,为分机号字段添加一个类以便于访问:
'<td class="extNo">' + d.extn + '</td>' +

当您显示子行时,应插入预渲染的内容details[],而不是调用format()函数:
if (row.child.isShown()) {
   row.child.hide();
   tr.removeClass('shown');
} else {
   row.child(details[row.index()]).show();            
   tr.addClass('shown');
}

创建一个筛选器,仅返回具有包含特定分机号的 details[] 子行的行:
function filterByDetailsExtNo(extNo) {
    $.fn.dataTable.ext.search.push(
    function(settings, data, dataIndex) {
       return $(details[dataIndex]).find('.extNo').text() == extNo;
    }    
  )
  table.draw();
  $.fn.dataTable.ext.search.pop();
}  

在您的输入处理程序中,使用自定义过滤器而不是column()搜索:

table.columns().every( function () {
    $( 'input', this.footer() ).on( 'keyup change', function () {
        filterByDetailsExtNo(this.value);
    });
});

分叉的JSFiddle示例 -> https://jsfiddle.net/7o67vhrz/


更新。要将上述过滤器应用于通用搜索框:

$('.dataTables_filter input')
   .off()
   .on('keyup', function() {
      filterByDetailsExtNo(this.value);
   });    

又一个分支的 JSFiddle -> https://jsfiddle.net/ds3qp41g/


最后一个例子。结合详细搜索和“本地”搜索。

function filterByDetailsExtNoAndInput(term) {
      $.fn.dataTable.ext.search.push(
        function(settings, data, dataIndex) {
            if ($(details[dataIndex]).find('.extNo').text() == term) return true;
            for (var i=0;i<data.length;i++) {
                if (data[i].toLowerCase().indexOf(term.toLowerCase())>=0) {
                    return true
                }    
            }   
            return false;
        }    
      )
      table.draw();
      $.fn.dataTable.ext.search.pop();
    }  

fiddle -> https://jsfiddle.net/h2u4fowj/


谢谢您的回复!我可能没有正确表达我的问题:是否有任何方法可以将此自定义过滤函数添加到右上角的DataTables全局搜索栏中?我只需要像这个链接中所示设置$.fn.dataTable.ext.search.push()方法吗? - cooltoast
嘿@cooltoast,过滤器在全局范围内始终有效 - 这就是为什么我在最后弹出(pop)它的原因。我不完全确定你的问题,你是否希望将搜索输入与上述过滤函数一般关联? - davidkonrad
在您的jsfiddle中,如果您在右上角搜索栏中搜索“1562”,则不会显示任何内容(但对于底部的单个列搜索栏确实有效)。由于我的实际应用程序没有这些列搜索栏,因此我想将自定义过滤器函数附加到右上角的搜索栏。这可以使用DataTables API完成吗? - cooltoast
嗯,现在似乎我无法搜索除分机号码以外的任何名称或内容(尝试搜索“Tiger”)。是否可能保留原始搜索栏功能并添加筛选功能以搜索分机号码?(再次抱歉没有正确解释我的问题) - cooltoast
2
@cooltoast,你真难满足 :) 这应该是易如反掌的事情,但我还是提供了一个示例和一个fiddle。这是我最后一次编辑了。 - davidkonrad
它可以工作!再次感谢@davidkonrad,你是真正的MVP - cooltoast

2

这是一个相当古老的主题,被接受的答案确实有效,但我想提出一种替代解决方案。

我也遇到了无法在子行中搜索的同样问题,我的解决方案是在表格末尾添加一个隐藏的<td>,其中包含子行中的数据 - 这样,索引器可以看到它但用户看不到。

对于有限的HTML,我添加了一个新列:

<th class="hidden">Data</th>

接下来,在DataTables调用中:

//Within var table = $('#table').DataTable( {....
columns : [
        //{ className : 'details-control'},
        { data : 'a' }, //a-e are the columns I want the user to see.
        { data : 'b' },
        { data : 'c' },
        { data : 'd' },
        { data : 'e' },            
        // this last one is my "index helper"
        { data : 'comments',
          render : function(data, type, full, meta) {
            return full.f + full.g + full.h + full.i;
          }
         }
    ],

那么,您只需要隐藏这一列。您可以通过DataTables的推荐方法来实现:

https://datatables.net/examples/basic_init/hidden_columns.html

或者您也可以采用我选择的方法:

"createdRow" : function (row,data,index) {
    $('td',row).eq(6).addClass('hidden');
}

//and the css...
.hidden {
 visibility: hidden;
}

在您的表格末尾只剩下一个包含所有子行内容的<td>,但它是不可见的,并且能与搜索框/过滤器一起使用。


我正在考虑最终不得不这样做,但我想避免这样做,因为这将导致我的表格产生臃肿的ajax调用。我的子行(实际上只有一行)的问题在于,该行是一个HTML表格,该表格中的字段是我想要搜索的内容,所以在主列中包含该表格只会让事情变得更麻烦。不过,我会看看能做些什么,也许能有所改善。 - Someone
这也是我的情况 - 我有一个子行,它只由一个巨大的HTML表组成,用其他我不想在“标题”行(用户点击的行)中显示的JSON记录填充。我发现返回额外隐藏行所需的时间对我来说并不是个问题 - 如果对你来说是问题的话,也许接受的答案就是解决方案? - Brian Powell
昨天在那个时间点上,我可能已经快完成工作了,所以没有继续做下去。不过,经过深思熟虑,我决定将我的子行字段从表格转换为json对象,并通过循环遍历该对象来动态生成子表。等我完成后,会向你反馈进展情况。因为我最终需要处理1000多行数据,所以我会尽力减少ajax请求数据的大小,以帮助提高效率。 - Someone
@BrianPowell 你有一个工作示例吗,在jfidde或其他地方?我想要创建一个带有可搜索子行的动态表格。我不懂js,但我可以复制粘贴。 - undefined

0
如果您有一个扩展名列表在一列中,那么您会想要像这样拆分它们。
              {"data": "extn", "visible": false,
               "render": function (data, type, row, meta) {

                        var htmlDetail = '';                            
                        yourList.forEach(function (item) {
                            htmlDetail += item.extn + '|';
                        });
                        return type === 'display' ? htmlDetail : htmlDetail;
              }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接