最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - jQuery DataTables filter rows based on multiple values - Stack Overflow

programmeradmin5浏览0评论

I am trying to have multiple filters that will hide/show rows on my datatable based on which filters are selected. My plan is to place the filter values in an array and pare those to the data-search attribute in the first column, but what I currently have does not work.

Here's a JSfiddle that I have plus code below /

HTML with checkboxes for filters and the table data..

<label>
    <input type="checkbox" name="cat" value="cat" class="filter"> Cats
</label>

<label>
    <input type="checkbox" name="dog" value="dog" class="filter"> Dogs
</label>

<table class="select_items">
    <thead>
        <tr>
            <th>Item</th>
            <th>Description</th>
            <th>Crest Allowed</th>
            <th>&nbsp;</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td data-search="cat">1</td>
            <td>Testing Bowl</td>
            <td>NO</td>
            <td><button class="button">Select</button></td>
        </tr>
        <tr>
            <td data-search="dog">32</td>
            <td>Cup Test</td>
            <td>NO</td>
            <td><button class="button">Select</button></td>
        </tr>
        <tr>
            <td data-search="dog">3335</td>
            <td>Bowl Test</td>
            <td>NO</td>
            <td><button class="button">Select</button></td>
        </tr>

    </tbody>
</table>

The JS..

var select_items = $('.select_items').DataTable();

var filters = [];

$('input.filter').on('change', function(){
   var filters = [];
   $("input.filter:checked").each(function(){

    var checkedBox = $(this).val();
    if (filters.indexOf(checkedBox) === -1){
        filters.push(checkedBox);
    }
   });

   console.log(filters);

   if(this.checked){
      $.fn.dataTable.ext.search.push(
         function (settings, data, dataIndex){
            return (data[0].indexOf(filters) > -1) ? true : false;
         }
      );
   } 

   select_items.draw();

   if(this.checked){
      $.fn.dataTable.ext.search.pop();    
   }
});

I am trying to have multiple filters that will hide/show rows on my datatable based on which filters are selected. My plan is to place the filter values in an array and pare those to the data-search attribute in the first column, but what I currently have does not work.

Here's a JSfiddle that I have plus code below https://jsfiddle/dmcgrew/06j4pxjk/3/

HTML with checkboxes for filters and the table data..

<label>
    <input type="checkbox" name="cat" value="cat" class="filter"> Cats
</label>

<label>
    <input type="checkbox" name="dog" value="dog" class="filter"> Dogs
</label>

<table class="select_items">
    <thead>
        <tr>
            <th>Item</th>
            <th>Description</th>
            <th>Crest Allowed</th>
            <th>&nbsp;</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td data-search="cat">1</td>
            <td>Testing Bowl</td>
            <td>NO</td>
            <td><button class="button">Select</button></td>
        </tr>
        <tr>
            <td data-search="dog">32</td>
            <td>Cup Test</td>
            <td>NO</td>
            <td><button class="button">Select</button></td>
        </tr>
        <tr>
            <td data-search="dog">3335</td>
            <td>Bowl Test</td>
            <td>NO</td>
            <td><button class="button">Select</button></td>
        </tr>

    </tbody>
</table>

The JS..

var select_items = $('.select_items').DataTable();

var filters = [];

$('input.filter').on('change', function(){
   var filters = [];
   $("input.filter:checked").each(function(){

    var checkedBox = $(this).val();
    if (filters.indexOf(checkedBox) === -1){
        filters.push(checkedBox);
    }
   });

   console.log(filters);

   if(this.checked){
      $.fn.dataTable.ext.search.push(
         function (settings, data, dataIndex){
            return (data[0].indexOf(filters) > -1) ? true : false;
         }
      );
   } 

   select_items.draw();

   if(this.checked){
      $.fn.dataTable.ext.search.pop();    
   }
});
Share Improve this question edited Jan 11, 2018 at 17:13 Dustin asked Jan 11, 2018 at 16:55 DustinDustin 4,45912 gold badges56 silver badges96 bronze badges 4
  • It works for me jsfiddle/06j4pxjk/2 – Hackerman Commented Jan 11, 2018 at 17:07
  • Not quite. When I have both selected I get no results.. I should see all 3 rows. Also if I select both then unselect Dogs I still see all 3 when I should just see the first row. – Dustin Commented Jan 11, 2018 at 17:12
  • You want the filters to act like an or instead of an and? – Hackerman Commented Jan 11, 2018 at 17:21
  • Yes so if somebody selects cat and dog it will show rows that have either cat or dog. – Dustin Commented Jan 11, 2018 at 17:34
Add a ment  | 

3 Answers 3

Reset to default 3

Considering, accepted answer refers to legacy interface fnFilter and, as of DataTables 1.10 new API is suggested, I'll allow myself to provide more up to date solution, which is, in my opinion, way more scalable, neat and simple:

//define statical data
var srcData = [
  {search: 'Cat', item: '1', descr: 'Testing Bowl', crest: 'NO'},
  {search: 'Dog', item: '32', descr: 'Cup Test', crest: 'NO'},
  {search: 'Dog', item: '3335', descr: 'Bowl Test', crest: 'NO'},
];
//define dataTable object
var dataTable = $('#mytable').DataTable({
  sDom: 't',
  data: srcData,
  columns: [
    {title: 'Item', data: 'item'},
    {title: 'Description', data: 'descr'},
    {title: 'Crest Allowed', data: 'crest'},
  ]
});
//put in place dynamically created checkboxes
var searchValues = [];
dataTable.data().sort().toArray().forEach(row => {
  if(searchValues.indexOf(row.search)==-1) searchValues.push(row.search);
});
var checkboxes = searchValues.reduce((html, item) => html += `<input type="checkbox" value="${item}" class="filter">${item}</input>`,'');
$(checkboxes).insertBefore($('#mytable'));
//employ $.fn.DataTable.ext.search
var lookupValues = [];
$.fn.DataTable.ext.search.push((settings, row, index, rowObj) => lookupValues.indexOf(rowObj.search) > -1 || lookupValues.length == 0);
//watch checkboxes and redraw table on change accordingly
$(".filter").on('change', () => {
  lookupValues = [...$('.filter:checked')].map(checkbox => $(checkbox).val());
  dataTable.draw();
});
<!doctype html>
<html>
<head>
  <script type="application/javascript" src="https://code.jquery./jquery-3.3.1.min.js"></script>
  <script type="application/javascript" src="https://cdn.datatables/1.10.19/js/jquery.dataTables.min.js"></script>
  <link rel="stylesheet" type="text/css" href="https://cdn.datatables/1.10.19/css/jquery.dataTables.min.css">
</head>
<body>
  <table id="mytable"></table>
</body>
</html>

I made a few changes in your code, using the fnFilter API:

Documentation: https://datatables/docs/DataTables/1.9.0/DataTable.html#fnFilter

$(function() {
  otable = $('.select_items').dataTable();
})

function filterme() {
  //build a regex filter string with an or(|) condition
  var types = $('input:checkbox[name="filter"]:checked').map(function() {
    return '^' + this.value + '\$';
  }).get().join('|');
  //filter in column 0, with an regex, no smart filtering, no inputbox,not case sensitive
  otable.fnFilter(types, 0, true, false, false, false);  
}

You can see it working here: JSFiddle demo

You have to check for the filter length.

If there is no filter, the $.fn.dataTable.ext.search.push function has to return true for ALL rows.

And, I think that search.pop() should apply on uncheck too...

var select_items = $('.select_items').DataTable();


$('input.filter').on('change', function(){
  var filters = [];
  $("input.filter:checked").each(function(){
    var checkedBox = $(this).val();
    if (filters.indexOf(checkedBox) === -1){
      filters.push(checkedBox);
    }
  });

  console.log(filters.length);

  $.fn.dataTable.ext.search.push(function(settings, data, dataIndex){
    if(filters.length>0){
      return (data[0].indexOf(filters) > -1) ? true : false;
    }else{
      return true;
    }
  });

  select_items.draw();
  $.fn.dataTable.ext.search.pop();
});

Updated Fiddle

发布评论

评论列表(0)

  1. 暂无评论