3

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 compare 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.net/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();    
   }
});
4
  • It works for me jsfiddle.net/06j4pxjk/2 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. Commented Jan 11, 2018 at 17:12
  • You want the filters to act like an or instead of an and? 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. Commented Jan 11, 2018 at 17:34

3 Answers 3

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.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>
  <table id="mytable"></table>
</body>
</html>

Sign up to request clarification or add additional context in comments.

Comments

2

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

Documentation: https://datatables.net/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

5 Comments

This is great.. but any idea why this doesn't work when wrapped in dom ready?
Nevermind.. I see there's a difference between dataTable() and DataTable(). I'll have to do some reading on that. Thanks for your help!
Do you know if there's a way to make this work across multiple columns? I have some data in column 2 that I'd like to filter by as well.
You can create another question with more detail and add the link as a comment here...I'll take a look :)
No problem.. here's the link: stackoverflow.com/questions/48229250/…
1

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.