Поиск JQuery Datatables внутри ввода и выбора

Использование JQuery Datatables со входами и выборами, как показано здесь: http://datatables.net/examples/api/form.html или если я использовал обработчик обработчика собственного столбца для ввода ввода и выбирает, как я могу заставить глобальный поиск в таблице работать?

Если вы посмотрите пример, вы заметите, что в поиск включен только первый столбец, только для чтения, что я могу сделать, чтобы включить другие столбцы в поиск?

Если вы посмотрите пример в ссылке в моем вопросе и введите "Токио" в поиск, все строки будут возвращены. Это связано с тем, что "Токио" является вариантом во всех выпадающих списках. Я бы хотел, чтобы только строки с Токио были отобраны для показа. Если вы наберете "33", вы увидите строки, даже если первая строка имеет значение "33" в первом столбце.

Я не могу найти какую-либо документацию о том, как определить, какое значение поиска для конкретной ячейки в datatable.

Ответ 1

Это не очень хорошо задокументировано. И кажется, что он работает по-разному или вообще не работает между (под) версиями. Я думаю, что dataTables предназначен для автоматического обнаружения HTML-столбцов, но по некоторым причинам, в большинстве случаев, это не так. Самый безопасный способ - создать собственный поисковый фильтр:

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

Это вернет 33 на <input> со значением 33 и Tokyo на <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> 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();
});

Для text() полей используйте text() вместо этого:

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

Это также имеет место при работе с <select>. Вам нужно будет обновить 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/ Попробуйте изменить содержимое входов и/или раскрывающихся списков и найдите новые значения...

Ответ 2

Если целью здесь является поиск по всем входным данным в таблице на основе текущих значений (и "обычных" ячеек), вам может потребоваться создать собственный настраиваемый поиск ($.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() == ''
});

Полное ДЕМО этого подхода вы можете найти ниже:

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();
});

Ответ 4

Лучше всего здесь просто обновить контейнер ячейки до нового значения из ввода и сохранить синхронизируемый объект данных данных с входом пользовательского интерфейса:

$("#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{
    height: 30px !important;
    padding: 2px;
    overflow: hidden;
}