JQuery Datatables 在输入和选择中搜索

IT技术 javascript jquery datatables
2021-01-14 12:30:24

使用带有输入和选择的 Jquery 数据表,如下所示:http : //datatables.net/examples/api/form.html 或者如果我使用自定义列渲染处理程序来生成输入并选择如何使全局表搜索工作?

如果您查看该示例,您会注意到只有第一列(只读列)包含在搜索中,我该怎么做才能将其他列包含在搜索中?

如果您在我的问题中查看链接中的示例并在搜索中输入“东京”,则会返回所有行。这是因为“东京”是所有下拉菜单中的一个选项。我只想显示选择了东京的行。如果您输入“33”,即使第一行的第一列中的值为“33”,您也看不到任何行。

我似乎找不到任何关于如何定义数据表中特定单元格的搜索值的文档。

5个回答

它没有很好的记录。它似乎在(子)版本之间工作不同,或者根本不工作。我认为 dataTables 旨在自动检测 HTML 列,但出于某种原因,大多数情况下,它不会。最安全的方法是创建自己的搜索过滤器:

$.fn.dataTableExt.ofnSearch['html-input'] = function(value) {
    return $(value).val();
};

这将返回值为 33 的33 on <input>,以及选择Tokyo 的 Tokyo on <select>然后将所需的列定义为类型html-input

var table = $("#example").DataTable({
    columnDefs: [
       { "type": "html-input", "targets": [1, 2, 3] }
    ] 
});

参见基于http://datatables.net/examples/api/form.html -> http://jsfiddle.net/a3o3yqkw/ 的演示


关于实时数据:问题是,基于类型的过滤器只被调用一次dataTables 然后缓存返回的值,因此它不需要一遍又一遍地“计算”所有值。幸运的是,dataTables 1.10.x有一个内置函数 for cellsrowspages调用invalidate它强制 dataTables 重置所选项目的缓存。

但是,在处理<input>'s 时也存在问题,即编辑值 not 正在更改value属性本身。因此,即使您调用invalidate(),您最终仍会过滤旧的“硬编码”值。

但我已经找到了解决方案。强制使用的当前值(新值)更改<input>value属性<input>然后调用invalidate

$("#example td input").on('change', function() {
  var $td = $(this).closest('td');
  $td.find('input').attr('value', this.value);
  table.cell($td).invalidate();
});

对于 textareas 使用text()

$("#example td textarea").on('change', function() {
  var $td = $(this).closest('td');
  $td.find('textarea').text(this.value);
  table.cell($td).invalidate(); 
});

处理<select>'s时也是如此您将需要更新selected相关属性<option>,然后更新invalidate()单元格:

$("#example td select").on('change', function() {
  var $td = $(this).closest('td');
  var value = this.value;
  $td.find('option').each(function(i, o) {
    $(o).removeAttr('selected');
    if ($(o).val() == value) $(o).attr('selected', true);
  })
  table.cell($td).invalidate();
}); 

分叉小提琴 -> http://jsfiddle.net/s2gbafuz/尝试更改输入和/或下拉列表的内容,并搜索新值...

嘿@Pavlo,感谢您的反馈。它不适用于 <selects> / dropdowns,因为我只使代码示例适用于 <inputs>。对 <select> 等价物进行编码非常简单。用新的代码示例和新的(工作)小提琴更新了答案。
2021-03-17 12:30:24
@davidkonrad 看起来是一个不错的解决方案,但似乎不起作用:| 我正在玩你的小提琴示例,当我更改其中一个输入或下拉列表的值时,它似乎在我进行搜索时忽略了更改
2021-03-23 12:30:24
@kralco626,是的,你当然是对的,没有想到这一点,这实际上是一个有趣的问题。见更新。——
2021-03-26 12:30:24
@davidkonrad 小提琴中的代码不适用于下拉列。它搜索良好,但如果您将更新单元格中的值,搜索仍使用旧值。我试图稍微改变你的代码来做到这一点,但现在没有运气。将尝试更多以使其有效。
2021-03-29 12:30:24
我喜欢这样,似乎是一个很好的解决方案。我唯一注意到的是,如果用户更改了值,搜索仍然适用于旧值而不是新值。关于如何解决这个问题的任何想法?
2021-04-05 12:30:24

如果这里的重点是根据实时值(和“常规”单元格)搜索表中的所有输入,您可能想要构建自己的自定义搜索 ( $.fn.DataTable.ext.search.push()):

//custom search function
$.fn.DataTable.ext.search.push((_,__,i) => {
  //get current row
  const currentTr = dataTable.row(i).node();
  //look for all <input>, <select> nodes within 
  //that row and check whether current value of
  //any of those contains searched string
  const inputMatch = $(currentTr)
    .find('select,input')
    .toArray()
    .some(input => $(input).val().toLowerCase().includes($('#search').val().toLowerCase()));
  //check whether "regular" cells contain the
  //value being searched
  const textMatch = $(currentTr)
    .children()
    .not('td:has("input,select")')
    .toArray()
    .some(td => $(td).text().toLowerCase().includes($('#search').val().toLowerCase()))
  //make final decision about match
  return inputMatch || textMatch || $('#search').val() == ''
});

您可以在下面找到此方法的完整演示

这应该搜索整个表而不是特定的列。

var table = $('#table').DataTable();

$('#input').on('keyup', function() {
  table.search(this.val).draw();
});
好的,我现在明白你在说什么了。我做了一些搜索,它似乎不是 DataTables 的一部分。不过我确实找到了这个他写了一个片段来搜索下拉列表的选定值。抱歉,我无法亲自为您提供代码片段!
2021-04-07 12:30:24
我正在尝试使用内置的全局搜索。我希望它仅从下拉列表中搜索选定的值。如果您在我的问题中查看链接中的示例并在搜索中输入“东京”,则会返回所有行。这是因为“东京”是所有下拉菜单中的一个选项。我只想显示选择了东京的行。如果您输入“33”,即使第一行的第一列中的值为“33”,您也看不到任何行。
2021-04-09 12:30:24

最好的做法是将单元格容器更新为输入中的新值,并使数据表数据对象与 UI 输入保持同步:

$("#pagesTable td input,#pagesTable td select").on('change', function () {
   var td = $(this).closest("td");
   dataTable.api().cell(td).data(this.value);
});

Textarea替换你的输入,并在下面添加 css。它会让你的 textarea 看起来像一个输入。

textarea{
    height: 30px !important;
    padding: 2px;
    overflow: hidden;
}