1

I'm using Datatables 1.10.19 though I would happily upgrade if that will help.

I have an application with several tables on the same page. For one of those tables I want to offer the user the option to do a negative search. They enter a value and see all the rows that don't have that value.

So far as I can see the search() API allows simple text or regex criteria. I've seen examples such as this.

var allTables = $('table.dataTable').DataTable();
 
allTables.column( 0 ).search( 'mySearchTerm', true, false ).draw();

Some regex dialects support negative look ahead so regex such as those described in this answer would allow me to specify negation, but it appears that that the regex engine in use in Datatables does not work with such expressions.

My alternative is to use a filter function which I can establish with this:

$.fn.dataTable.ext.search.push()

However that seems to be a global construct affecting all tables, which I really don't want.

Any suggestions please?

djna
  • 54,992
  • 14
  • 74
  • 117

1 Answers1

1

You can use $.fn.dataTable.ext.search.push() - but it requires some additional work, to handle the fact (as you point out) that this is a global function, affecting all tables.

The following is not a full implementation, but shows the main points:

The Approach

My example uses 2 tables, with hard-coded data in each HTML table.

Each table is initialized as follows:

  $(document).ready(function() {

    // ---- first table with custom search ---------//

    var table_a = $('#example_a').DataTable( {
      pageLength: 10
    } );

    // remove the default DT search events - otherwise
    // they will always fire before our custom event:
    $( "#example_a_filter input" ).unbind();

    // add our custom filter event for table_a:
    $('#example_a_filter input').keyup( function( e ) {
        table_a.draw();
    } );

    // ---- second table with DT default search ----//

    var table_b = $('#example_b').DataTable( {
      pageLength: 10
    } );

  } );

For my custom search function, I make use of the fact that the function includes a settings parameter which we can use to see which table is being searched:

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

      var tableID = settings.nTable.id;
      var searchTerm = $('#' + tableID + '_filter input').val()

      //console.log( tableID );
      //console.log( searchTerm );
      //console.log( searchData );

      switch(tableID) {
        case 'example_a':
          if (searchTerm === '') {
            return true;
          } else {
            show_me = true;
            searchData.forEach(function (item, index) {
              if (show_me && item.includes(searchTerm)) {
                show_me = false;
              }
            });
            return show_me;
          }
          break;
        default:
          // for all other tables, pass through the rows
          // already filtered by the default DT filter:
          return true;
      }
    }
  );

The following line is where we ID which table is being filtered:

var tableID = settings.nTable.id;

After that, I can use a switch statement to handle each table's search separately.

In the default case (for example_b), I'm just passing through what was already filtered by the DT default search:

default: return true;

The above filter looks like this when I search each table for the letter x:

enter image description here

Incomplete Implementation

This logic is incomplete for the custom search logic. It assumes the search term is a single string. If I enter "x y" in the input field, that will exclude all records where a field contains "x y" - which is probably not what you want.

You probably want the exact negation of the standard search - so the input term would need to be split on spaces and each sub-term (x and y) would need to be checked separately across each row of data.

andrewJames
  • 19,570
  • 8
  • 19
  • 51
  • Thank you; this answers my question, and gives nicely detailed examples that surely will be helpful to others. – djna Oct 05 '20 at 04:15