Prevent DataTables custom filter from affecting all tables on a page
Asked Answered
P

5

7

When we add a custom filter to DataTables:

$.fn.dataTable.ext.search.push(function(settings, data, dataIndex) {
  ...
})

it works as expected on one table. However, if we have multiple tables on the same page, all filters affects all tables. How to create custom filters that only affect a specific table?

Pharos answered 19/3, 2019 at 14:1 Comment(0)
P
7

All custom filters works globally because $.fn.dataTable.ext.search is a global array any DataTable on a page takes into consideration when they are redrawn. There is no way around it, it is simply how DT is designed.

However, by using DT's plug-in architecture and simply hook into the relevant events, it is easy to replace the global array with local custom filters when needed, if any :

$.fn.dataTable.Api.register('filter.push', function(fn, draw) {
  if (!this.__customFilters) {
    var filters = this.__customFilters = [] 
    this.on('mousedown preDraw.dt', function() {
      $.fn.dataTable.ext.search = filters
    })
  }
  this.__customFilters.push(fn)
  $.fn.dataTable.ext.search = this.__customFilters 
  this.draw()
})

$.fn.dataTable.Api.register('filter.pop', function() {
  if (!this.__customFilters) return
  this.__customFilters.pop()
})

Thats it. Now, if you have a page with multiple DataTables, and you want a custom filter to work for one specific table only :

table.filter.push(function(settings, data, dataIndex) {
  ...
})

If you want to remove the filter table.filter.pop()

Here is a demo with three tables on the same page, each of them having their own custom filter implemented -> http://jsfiddle.net/gc4ow8yr/

Pharos answered 19/3, 2019 at 14:32 Comment(0)
C
6

In your custom filter, check for settings.nTable.id and take action if the id matches the id of your table.

Credits to 'kthorngren' who posted it here initially.

/* Custom filtering function which will search data in column four between two values */
$.fn.dataTable.ext.search.push(
    function( settings, data, dataIndex ) {
      console.log(settings.nTable.id);
      if ( settings.nTable.id !== 'example' ) {
        return true;
      }
        var min = parseInt( $('#min').val(), 10 );
        var max = parseInt( $('#max').val(), 10 );
        var age = parseFloat( data[3] ) || 0; // use data for the age column
 
        if ( ( isNaN( min ) && isNaN( max ) ) ||
             ( isNaN( min ) && age <= max ) ||
             ( min <= age   && isNaN( max ) ) ||
             ( min <= age   && age <= max ) )
        {
            return true;
        }
        return false;
    }
);
 
/* Custom filtering function which will search data in column four between two values */
$.fn.dataTable.ext.search.push(
    function( settings, data, dataIndex ) {
      console.log(settings.nTable.id);
      if ( settings.nTable.id !== 'example2' ) {
        return true;
      }
        var min = parseInt( $('#min2').val(), 10 );
        var max = parseInt( $('#max2').val(), 10 );
        var age = parseFloat( data[3] ) || 0; // use data for the age column
 
        if ( ( isNaN( min ) && isNaN( max ) ) ||
             ( isNaN( min ) && age <= max ) ||
             ( min <= age   && isNaN( max ) ) ||
             ( min <= age   && age <= max ) )
        {
            return true;
        }
        return false;
    }
);
 

$(document).ready( function () {
  var table = $('#example').DataTable({
    dom: 'tir'
  });
  var table2 = $('#example2').DataTable({
    dom: 'tir'
  });
  
    // Event listener to the two range filtering inputs to redraw on input
    $('#min, #max').keyup( function() {
        table.draw();
        table2.draw();
    } );

  
    // Event listener to the two range filtering inputs to redraw on input
    $('#min2, #max2').keyup( function() {
        table.draw();
        table2.draw();
    } );

});
body {
  font: 90%/1.45em "Helvetica Neue", HelveticaNeue, Verdana, Arial, Helvetica, sans-serif;
  margin: 0;
  padding: 0;
  color: #333;
  background-color: #fff;
}
<script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
<link href="https://nightly.datatables.net/css/jquery.dataTables.css" rel="stylesheet" type="text/css" />
<script src="https://nightly.datatables.net/js/jquery.dataTables.js"></script>
<div class="container">
      <table border="0" cellspacing="5" cellpadding="5">
        <tbody><tr>
            <td>Minimum age:</td>
            <td><input type="text" id="min" name="min"></td>
        </tr>
        <tr>
            <td>Maximum age:</td>
            <td><input type="text" id="max" name="max"></td>
        </tr>
    </tbody>
      <table id="example" class="display nowrap" width="100%">
        <thead>
          <tr>
            <th>Name</th>
            <th>Position</th>
            <th>Office</th>
            <th>Age</th>
            <th>Start date</th>
            <th>Salary</th>
          </tr>
        </thead>

        <tfoot>
          <tr>
            <th>Name</th>
            <th>Position</th>
            <th>Office</th>
            <th>Age</th>
            <th>Start date</th>
            <th>Salary</th>
          </tr>
        </tfoot>

        <tbody>
          <tr>
            <td>Tiger Nixon</td>
            <td>System Architect</td>
            <td>Edinburgh</td>
            <td>61</td>
            <td>2011/04/25</td>
            <td>$3,120</td>
          </tr>
          <tr>
            <td>Garrett Winters</td>
            <td>Director</td>
            <td>Edinburgh</td>
            <td>63</td>
            <td>2011/07/25</td>
            <td>$5,300</td>
          </tr>
          <tr>
            <td>Ashton Cox</td>
            <td>Technical Author</td>
            <td>San Francisco</td>
            <td>66</td>
            <td>2009/01/12</td>
            <td>$4,800</td>
          </tr>
          <tr>
            <td>Cedric Kelly</td>
            <td>Javascript Developer</td>
            <td>Edinburgh</td>
            <td>22</td>
            <td>2012/03/29</td>
            <td>$3,600</td>
          </tr>
          <tr>
            <td>Jenna Elliott</td>
            <td>Financial Controller</td>
            <td>Edinburgh</td>
            <td>33</td>
            <td>2008/11/28</td>
            <td>$5,300</td>
          </tr>
          <tr>
            <td>Brielle Williamson</td>
            <td>Integration Specialist</td>
            <td>New York</td>
            <td>61</td>
            <td>2012/12/02</td>
            <td>$4,525</td>
          </tr>
          <tr>
            <td>Herrod Chandler</td>
            <td>Sales Assistant</td>
            <td>San Francisco</td>
            <td>59</td>
            <td>2012/08/06</td>
            <td>$4,080</td>
          </tr>
          <tr>
            <td>Rhona Davidson</td>
            <td>Integration Specialist</td>
            <td>Edinburgh</td>
            <td>55</td>
            <td>2010/10/14</td>
            <td>$6,730</td>
          </tr>
          <tr>
            <td>Colleen Hurst</td>
            <td>Javascript Developer</td>
            <td>San Francisco</td>
            <td>39</td>
            <td>2009/09/15</td>
            <td>$5,000</td>
          </tr>
          <tr>
            <td>Sonya Frost</td>
            <td>Software Engineer</td>
            <td>Edinburgh</td>
            <td>23</td>
            <td>2008/12/13</td>
            <td>$3,600</td>
          </tr>
          <tr>
            <td>Jena Gaines</td>
            <td>System Architect</td>
            <td>London</td>
            <td>30</td>
            <td>2008/12/19</td>
            <td>$5,000</td>
          </tr>
          <tr>
            <td>Quinn Flynn</td>
            <td>Financial Controller</td>
            <td>Edinburgh</td>
            <td>22</td>
            <td>2013/03/03</td>
            <td>$4,200</td>
          </tr>
          <tr>
            <td>Charde Marshall</td>
            <td>Regional Director</td>
            <td>San Francisco</td>
            <td>36</td>
            <td>2008/10/16</td>
            <td>$5,300</td>
          </tr>
          <tr>
            <td>Haley Kennedy</td>
            <td>Senior Marketing Designer</td>
            <td>London</td>
            <td>43</td>
            <td>2012/12/18</td>
            <td>$4,800</td>
          </tr>
          <tr>
            <td>Tatyana Fitzpatrick</td>
            <td>Regional Director</td>
            <td>London</td>
            <td>19</td>
            <td>2010/03/17</td>
            <td>$2,875</td>
          </tr>
          <tr>
            <td>Michael Silva</td>
            <td>Senior Marketing Designer</td>
            <td>London</td>
            <td>66</td>
            <td>2012/11/27</td>
            <td>$3,750</td>
          </tr>
          <tr>
            <td>Paul Byrd</td>
            <td>Javascript Developer</td>
            <td>New York</td>
            <td>64</td>
            <td>2010/06/09</td>
            <td>$5,000</td>
          </tr>
          <tr>
            <td>Gloria Little</td>
            <td>Systems Administrator</td>
            <td>New York</td>
            <td>59</td>
            <td>2009/04/10</td>
            <td>$3,120</td>
          </tr>
          <tr>
            <td>Bradley Greer</td>
            <td>Software Engineer</td>
            <td>London</td>
            <td>41</td>
            <td>2012/10/13</td>
            <td>$3,120</td>
          </tr>
          <tr>
            <td>Dai Rios</td>
            <td>System Architect</td>
            <td>Edinburgh</td>
            <td>35</td>
            <td>2012/09/26</td>
            <td>$4,200</td>
          </tr>
          <tr>
            <td>Jenette Caldwell</td>
            <td>Financial Controller</td>
            <td>New York</td>
            <td>30</td>
            <td>2011/09/03</td>
            <td>$4,965</td>
          </tr>
          <tr>
            <td>Yuri Berry</td>
            <td>System Architect</td>
            <td>New York</td>
            <td>40</td>
            <td>2009/06/25</td>
            <td>$3,600</td>
          </tr>
          <tr>
            <td>Caesar Vance</td>
            <td>Technical Author</td>
            <td>New York</td>
            <td>21</td>
            <td>2011/12/12</td>
            <td>$4,965</td>
          </tr>
          <tr>
            <td>Doris Wilder</td>
            <td>Sales Assistant</td>
            <td>Edinburgh</td>
            <td>23</td>
            <td>2010/09/20</td>
            <td>$4,965</td>
          </tr>
          <tr>
            <td>Angelica Ramos</td>
            <td>System Architect</td>
            <td>London</td>
            <td>36</td>
            <td>2009/10/09</td>
            <td>$2,875</td>
          </tr>
          <tr>
            <td>Gavin Joyce</td>
            <td>Developer</td>
            <td>Edinburgh</td>
            <td>42</td>
            <td>2010/12/22</td>
            <td>$4,525</td>
          </tr>
          <tr>
            <td>Jennifer Chang</td>
            <td>Regional Director</td>
            <td>London</td>
            <td>28</td>
            <td>2010/11/14</td>
            <td>$4,080</td>
          </tr>
          <tr>
            <td>Brenden Wagner</td>
            <td>Software Engineer</td>
            <td>San Francisco</td>
            <td>18</td>
            <td>2011/06/07</td>
            <td>$3,750</td>
          </tr>
          <tr>
            <td>Ebony Grimes</td>
            <td>Software Engineer</td>
            <td>San Francisco</td>
            <td>48</td>
            <td>2010/03/11</td>
            <td>$2,875</td>
          </tr>
          <tr>
            <td>Russell Chavez</td>
            <td>Director</td>
            <td>Edinburgh</td>
            <td>20</td>
            <td>2011/08/14</td>
            <td>$3,600</td>
          </tr>
         </tbody>
      </table>

        
      <table border="0" cellspacing="5" cellpadding="5">
        <tbody><tr>
            <td>Minimum age:</td>
            <td><input type="text" id="min2" name="min"></td>
        </tr>
        <tr>
            <td>Maximum age:</td>
            <td><input type="text" id="max2" name="max"></td>
        </tr>
    </tbody>

      <table id="example2" class="display nowrap" width="100%">
        <thead>
          <tr>
            <th>Name</th>
            <th>Position</th>
            <th>Office</th>
            <th>Age</th>
            <th>Start date</th>
            <th>Salary</th>
          </tr>
        </thead>

        <tfoot>
          <tr>
            <th>Name</th>
            <th>Position</th>
            <th>Office</th>
            <th>Age</th>
            <th>Start date</th>
            <th>Salary</th>
          </tr>
        </tfoot>

         <tbody>
         <tr>
            <td>Michelle House</td>
            <td>Integration Specialist</td>
            <td>Edinburgh</td>
            <td>37</td>
            <td>2011/06/02</td>
            <td>$3,750</td>
          </tr>
          <tr>
            <td>Suki Burks</td>
            <td>Developer</td>
            <td>London</td>
            <td>53</td>
            <td>2009/10/22</td>
            <td>$2,875</td>
          </tr>
          <tr>
            <td>Prescott Bartlett</td>
            <td>Technical Author</td>
            <td>London</td>
            <td>27</td>
            <td>2011/05/07</td>
            <td>$6,730</td>
          </tr>
          <tr>
            <td>Gavin Cortez</td>
            <td>Technical Author</td>
            <td>San Francisco</td>
            <td>22</td>
            <td>2008/10/26</td>
            <td>$6,730</td>
          </tr>
          <tr>
            <td>Martena Mccray</td>
            <td>Integration Specialist</td>
            <td>Edinburgh</td>
            <td>46</td>
            <td>2011/03/09</td>
            <td>$4,080</td>
          </tr>
          <tr>
            <td>Unity Butler</td>
            <td>Senior Marketing Designer</td>
            <td>San Francisco</td>
            <td>47</td>
            <td>2009/12/09</td>
            <td>$3,750</td>
          </tr>
          <tr>
            <td>Howard Hatfield</td>
            <td>Financial Controller</td>
            <td>San Francisco</td>
            <td>51</td>
            <td>2008/12/16</td>
            <td>$4,080</td>
          </tr>
          <tr>
            <td>Hope Fuentes</td>
            <td>Financial Controller</td>
            <td>San Francisco</td>
            <td>41</td>
            <td>2010/02/12</td>
            <td>$4,200</td>
          </tr>
          <tr>
            <td>Vivian Harrell</td>
            <td>System Architect</td>
            <td>San Francisco</td>
            <td>62</td>
            <td>2009/02/14</td>
            <td>$4,965</td>
          </tr>
          <tr>
            <td>Timothy Mooney</td>
            <td>Financial Controller</td>
            <td>London</td>
            <td>37</td>
            <td>2008/12/11</td>
            <td>$4,200</td>
          </tr>
          <tr>
            <td>Jackson Bradshaw</td>
            <td>Director</td>
            <td>New York</td>
            <td>65</td>
            <td>2008/09/26</td>
            <td>$5,000</td>
          </tr>
          <tr>
            <td>Miriam Weiss</td>
            <td>Support Engineer</td>
            <td>Edinburgh</td>
            <td>64</td>
            <td>2011/02/03</td>
            <td>$4,965</td>
          </tr>
          <tr>
            <td>Bruno Nash</td>
            <td>Software Engineer</td>
            <td>London</td>
            <td>38</td>
            <td>2011/05/03</td>
            <td>$4,200</td>
          </tr>
          <tr>
            <td>Odessa Jackson</td>
            <td>Support Engineer</td>
            <td>Edinburgh</td>
            <td>37</td>
            <td>2009/08/19</td>
            <td>$3,600</td>
          </tr>
          <tr>
            <td>Thor Walton</td>
            <td>Developer</td>
            <td>New York</td>
            <td>61</td>
            <td>2013/08/11</td>
            <td>$3,600</td>
          </tr>
          <tr>
            <td>Finn Camacho</td>
            <td>Support Engineer</td>
            <td>San Francisco</td>
            <td>47</td>
            <td>2009/07/07</td>
            <td>$4,800</td>
          </tr>
          <tr>
            <td>Elton Baldwin</td>
            <td>Data Coordinator</td>
            <td>Edinburgh</td>
            <td>64</td>
            <td>2012/04/09</td>
            <td>$6,730</td>
          </tr>
          <tr>
            <td>Zenaida Frank</td>
            <td>Software Engineer</td>
            <td>New York</td>
            <td>63</td>
            <td>2010/01/04</td>
            <td>$4,800</td>
          </tr>
          <tr>
            <td>Zorita Serrano</td>
            <td>Software Engineer</td>
            <td>San Francisco</td>
            <td>56</td>
            <td>2012/06/01</td>
            <td>$5,300</td>
          </tr>
          <tr>
            <td>Jennifer Acosta</td>
            <td>Javascript Developer</td>
            <td>Edinburgh</td>
            <td>43</td>
            <td>2013/02/01</td>
            <td>$2,875</td>
          </tr>
          <tr>
            <td>Cara Stevens</td>
            <td>Sales Assistant</td>
            <td>New York</td>
            <td>46</td>
            <td>2011/12/06</td>
            <td>$4,800</td>
          </tr>
          <tr>
            <td>Hermione Butler</td>
            <td>Director</td>
            <td>London</td>
            <td>47</td>
            <td>2011/03/21</td>
            <td>$4,080</td>
          </tr>
          <tr>
            <td>Lael Greer</td>
            <td>Systems Administrator</td>
            <td>London</td>
            <td>21</td>
            <td>2009/02/27</td>
            <td>$3,120</td>
          </tr>
          <tr>
            <td>Jonas Alexander</td>
            <td>Developer</td>
            <td>San Francisco</td>
            <td>30</td>
            <td>2010/07/14</td>
            <td>$5,300</td>
          </tr>
          <tr>
            <td>Shad Decker</td>
            <td>Regional Director</td>
            <td>Edinburgh</td>
            <td>51</td>
            <td>2008/11/13</td>
            <td>$5,300</td>
          </tr>
          <tr>
            <td>Michael Bruce</td>
            <td>Javascript Developer</td>
            <td>Edinburgh</td>
            <td>29</td>
            <td>2011/06/27</td>
            <td>$4,080</td>
          </tr>
          <tr>
            <td>Donna Snider</td>
            <td>System Architect</td>
            <td>New York</td>
            <td>27</td>
            <td>2011/01/25</td>
            <td>$3,120</td>
          </tr>
        </tbody>
      </table>
    </div>
Circumlocution answered 19/3, 2019 at 14:27 Comment(5)
Yes, I have over the time posted similar answers as well :) This question came out of comments to several already answered questions today; again a user was confused so I decided to find a more robust solution that works without the "is this the right table"-overhead in the filters. The overhead makes it ugly and hard to maintain, and you cannot just copy paste filters. So +1 to you, but I think I finally have found a more elegant way. Besides that, this is caused by very poor design in DT, we should never need to do hacks like this in the first place :)Pharos
I would, without a doubt, mark yours as an answer if I was the OP I know you will have to wait 2 days to mark yours. The solution is so clean and easy to understand. I don't need to hunt for specific code to remove it, just pop it! Yes, DataTables could have handled it better, but it is good at least we have an option to come up with a hack.Circumlocution
:) this anwer is what I was most inspired by. settings.nTable.id !== 'example' is pretty simple imo, don't need to modify how datatables works. I just didn't know before that settings had this nTable and id which you could check/compare against. Overall I think DataTables is pretty capable once you're more familiar... but I think some more common use-cases should have more examples.Lipolysis
@mmcrae, you are actually right, I guess. If you just have one or two filters, then perhaps it is more logical that the filter itself decides what table it should target. I was thinking many filters and reuseability. Anything I can reuse is to me a gain,, a good filter could be used over and over.Pharos
@Pharos btw I posted an answer, that I think sums of a few good ideas, to this related/popular question #31458560Lipolysis
P
2

The accepted answer from davidkonrad almost works. It just lacks a code line in 'filter.pop'. Furthermore, the mouse event in 'filter.push' is particular to his sample, so it is no real need of it. Below the updated code:

$.fn.dataTable.Api.register('filter.push', function (fn, draw) {
    if (!this.__customFilters) {
        var filters = this.__customFilters = [];
        $.fn.dataTable.ext.search = filters;
     }
    this.__customFilters.push(fn);
    $.fn.dataTable.ext.search = this.__customFilters;
    this.draw();
})

$.fn.dataTable.Api.register('filter.pop', function () {
    if (!this.__customFilters) {
        var filters = this.__customFilters = [];
    }
    this.__customFilters.pop();
    $.fn.dataTable.ext.search = this.__customFilters;
})
Paries answered 21/9, 2021 at 15:14 Comment(0)
L
1
var detailDT = $("#staging-detail-table").DataTable();

var selectedHeaderId = $(...).click...

$.fn.dataTable.ext.search.push(
       function (settings, searchData, dataIndex, rowData) {

            // This is a global call-back, so check what table is getting sent thru
            // for different search logic.
            // This is triggered any time any table is re-drawn.

            // Detail grid
            if (settings.nTable.id == "staging-detail-table") {
                if (!selectedHeaderId) {
                    // no header was selected. show everything
                    return true;
                } else {
                    var $trDetailDT = $(detailDT.row(dataIndex).node());
                    var headerId = $trDetailDT.data("headerid");

                    return selectedHeaderId == headerId;
                }
            }

            return true; // it wasnot the staging data table. Don't filter/limit.
        }
)

detailDT is a reference to the DataTable I want to filter.

selectedHeaderId is the value I want to filter by - would have been set by some other jQuery user interaction etc. before calling detailDT.draw() which triggers the search.

Key part is calling settings.nTable.id == "staging-detail-table" which checks the HTML id of the data table, so you can apply filtering to the id you want.

Lipolysis answered 26/3, 2019 at 22:2 Comment(0)
E
-2

Your simply doing a wrong approach here. $.fn.dataTable.ext.search.push has another purpose which you should never use when you multiple datatables in the page that you want to differently filter. The easiest way to build a custom search for a specific table is to build an array of unique ids for your data and later search it in your column id. Example: enter image description here

Expectoration answered 18/1, 2020 at 5:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.