JQuery Datatables 在输入中搜索并选择
Posted
技术标签:
【中文标题】JQuery Datatables 在输入中搜索并选择【英文标题】:JQuery Datatables search within input and select 【发布时间】:2015-03-07 07:09:03 【问题描述】:使用带有输入和选择的 Jquery 数据表,如下所示:http://datatables.net/examples/api/form.html 或者如果我使用自定义列渲染处理程序来生成输入并选择如何使全局表搜索工作?
如果您查看示例,您会注意到搜索中只包含第一列,即只读列,如何才能将其他列包含在搜索中?
如果您在我的问题的链接中查看示例并在搜索中输入“东京”,则所有行都会返回。这是因为“东京”是所有下拉菜单中的一个选项。我只想显示选择东京的行。如果您输入“33”,即使第一行在第一列中的值为“33”,您也看不到任何行。
我似乎找不到任何关于如何定义数据表中特定单元格的搜索值的文档。
【问题讨论】:
【参考方案1】:它没有很好的记录。在(子)版本之间,它的工作方式似乎不同,或者根本不工作。我认为 dataTables 旨在自动检测 HTML 列,但由于某种原因,大多数时候,它不会。最安全的方法是创建自己的搜索过滤器:
$.fn.dataTableExt.ofnSearch['html-input'] = function(value)
return $(value).val();
;
这将在 <input>
上返回 33,值为 33,在 <select>
上返回 Tokyo,其中选择了东京。然后将所需的列定义为 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 有一个用于cells
、rows
和pages
的内置函数,称为invalidate
,它强制dataTables 重置所选项目的缓存。
但是,在处理<input>
时也存在问题,即编辑值不是更改value
属性本身。因此,即使您调用invalidate()
,您仍将最终过滤旧的“硬编码”值。
但是我已经找到了解决方案。强制使用<input>
的当前值(新值)更改<input>
的value
属性,然后然后 调用invalidate
:
$("#example td input").on('change', function()
var $td = $(this).closest('td');
$td.find('input').attr('value', this.value);
table.cell($td).invalidate();
);
对于文本区域,请改用text()
:
$("#example td textarea").on('change', function()
var $td = $(this).closest('td');
$td.find('textarea').text(this.value);
table.cell($td).invalidate();
);
在处理<select>
时也是如此。您需要更新相关<option>
的selected
属性,然后还需要更新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();
);
forked fiddle -> http://jsfiddle.net/s2gbafuz/ 尝试更改输入和/或下拉列表的内容,然后搜索新值...
【讨论】:
我喜欢这样,似乎是一个很好的解决方案。我唯一注意到的是,如果用户更改了值,搜索仍然适用于旧值而不是新值。关于如何解决这个问题的任何想法? @kralco626,是的,你当然是对的,没有想到这一点,这实际上是一个有趣的问题。见更新。 —— @davidkonrad 看起来是一个不错的解决方案,但它似乎不起作用:|我正在玩你的小提琴示例,当我更改其中一个输入或下拉列表的值时,它似乎在我进行搜索时忽略了更改 @davidkonrad 小提琴中的代码不适用于下拉列表。它搜索得很好,但如果你要更新单元格中的值,搜索仍然使用旧值。我试图改变你的代码来做到这一点,但现在没有运气。将尝试更多以使其发挥作用。 嘿@Pavlo,感谢您的反馈。它不适用于如果这里的目的是根据实时值(和“常规”单元格)搜索表格中的所有输入,您可能需要构建自己的自定义搜索 ($.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() == ''
);
您可以在下面找到此方法的完整DEMO:
const srcData = [id:1,item:'apple',category:'fruit',id:2,item:'banana',category:'fruit',id:3,item:'goosberry',category:'berry',id:4,item:'eggplant',category:'vegie',id:5,item:'carrot',category:'vegie'];
const dataTable = $('table').DataTable(dom:'t',data:srcData,columns:[title:'Id',data:'id',title:'Item',data:'item',render:data=>`<input value="$data"></input>`,title:'Category',data:'category',render:data=>`<select>$['fruit', 'vegie', 'berry'].reduce((options, item) => options+='<option value="'+item+'" '+(item == data ? 'selected' : '')+'>'+item+'</option>', '<option value=""></option>')</select>`]);
$.fn.DataTable.ext.search.push((_,__,i) =>
const currentTr = dataTable.row(i).node();
const inputMatch = $(currentTr)
.find('select,input')
.toArray()
.some(input => $(input).val().toLowerCase().includes( $('#search').val().toLowerCase()));
const textMatch = $(currentTr)
.children()
.not('td:has("input,select")')
.toArray()
.some(td => $(td).text().toLowerCase().includes($('#search').val().toLowerCase()))
return inputMatch || textMatch || $('#search').val() == ''
);
$('#search').on('keyup', () => dataTable.draw());
<!doctype html><html><head><script type="application/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script><script type="application/javascript" src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script><link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css"></head><body><input id="search"></input><table></table></body></html>
【讨论】:
【参考方案3】:这应该搜索整个表格而不是特定的列。
var table = $('#table').DataTable();
$('#input').on('keyup', function()
table.search(this.val).draw();
);
【讨论】:
我正在尝试使用内置的全局搜索。我希望它只从下拉列表中搜索选定的值。如果您在我的问题的链接中查看示例并在搜索中键入“东京”,则会返回所有行。这是因为“东京”是所有下拉菜单中的一个选项。我只想显示选择东京的行。如果您输入“33”,即使第一行在第一列中的值为“33”,您也看不到任何行。 好的,我明白你现在在说什么了。我做了一些搜索,它似乎不是 DataTables 的一部分。但是我确实找到了this。他编写了一个 sn-p 搜索下拉列表的选定值。抱歉,我无法亲自为您提供 sn-p!【参考方案4】:这里最好的做法是将单元格容器更新为输入中的新值,并使数据表数据对象与 UI 输入保持同步:
$("#pagesTable td input,#pagesTable td select").on('change', function ()
var td = $(this).closest("td");
dataTable.api().cell(td).data(this.value);
);
【讨论】:
【参考方案5】:用Textarea替换你的输入,并添加下面的css。它会让你的 textarea 看起来像一个输入。
textarea
height: 30px !important;
padding: 2px;
overflow: hidden;
【讨论】:
以上是关于JQuery Datatables 在输入中搜索并选择的主要内容,如果未能解决你的问题,请参考以下文章