Combining searches

Combining searches

smasonsmason Posts: 25Questions: 11Answers: 0
edited January 2021 in Free community support

I have a use case where I'm presenting two checkboxes to a user. These checkboxes will both do different "searches" on the datatable and filter it appropriately. They look for the value of a data attribute on the <tr> element.

Individually they work fine. However I want them to chain together meaning when one is clicked, do that one and when another is clicked apply that one, along with the first one's value.

I can't get them to work together because when I toggle one off, I have to do
$.fn.dataTable.ext.search.pop();
and that removes both filters!

How can I remove the specific filter relating to just that checkbox?

Search application functions

function hidePickedRecords(){
        $.fn.dataTable.ext.search.push(
        function(settings, data, dataIndex) {
            var oTable = new $.fn.dataTable.Api( settings );  // Get API instance for table
            return $(oTable.row(dataIndex).node()).attr('data-picked-row') == 0;
        });
    }

    function hideUnReadyRecords(){
        $.fn.dataTable.ext.search.push(
        function(settings, data, dataIndex) {
            var oTable = new $.fn.dataTable.Api( settings );  // Get API instance for table
            return $(oTable.row(dataIndex).node()).attr('data-fully-ready') == 1;
        });
    }

Event listeners for the checkbox changes:

 // Hide Picked checkbox change
            $("#hide-picked-checkbox").on("change", function(){
                let showPickedRecords = $(this).is(":checked") ? 0 : 1;

                if ( showPickedRecords ) {
                    $.fn.dataTable.ext.search.pop();     // removes filter already in place
                }
                else {
                    hidePickedRecords();
                }
                oTable.draw();

            });

        // Show Un-Ready checkbox change
            $("#show-un-ready").on("change ", function(){
                let showUnReadyRecords = $(this).is(":checked") ? 1 : 0;

                if ( showUnReadyRecords ) {
                    $.fn.dataTable.ext.search.pop(); // removes any filter already in place
                }
                else {
                    hideUnReadyRecords();
                }
                oTable.draw();
            });

Answers

  • allanallan Posts: 63,522Questions: 1Answers: 10,473 Site admin

    The way I’d suggest approaching this is actually not to add and remove the search functions from the array dynamically, but rather inside each function have a check to see if it should be active or not. e.g. in pseudo code:

    function () {
      if ( ! unreadyFilter ) {
        return true;
      }
    
      ... unready Filtering Logic
    }
    

    Then your checkbox can just toggle the unreadyFilter variable.

    If you do want to dynamically and and remove the functions, then don’t use anonymous functions. Instead use a traditional:

    function unreadyFilter (...) {
      ...
    }
    

    You can then add that to the array and also loop over the array to find the function when you want to remove it (i.e. get its index and use splice).

    Allan

  • smasonsmason Posts: 25Questions: 11Answers: 0

    I was able to combine both into one function and that did all the processing. Then push that onto the search.

    Final solution:

    The event listener:

     $("#hide-picked-checkbox, #hide-unready-checkbox").on("change", function(){                    
        $.fn.dataTable.ext.search.pop(); // removes filters already in place
        doTableFilters();  // <-custom function
        oTable.draw();
     });
    

    The custom function:

    function doTableFilters(){
            $.fn.dataTable.ext.search.push(
                function(settings, data, dataIndex) {
                    var oTable    = new $.fn.dataTable.Api( settings );  // Get API instance for table
    
                    let hidePickedRecords  = $("#hide-picked-checkbox").is(":checked")  ? 1 : 0;
                    let hideUnReadyRecords = $("#hide-unready-checkbox").is(":checked") ? 1 : 0;
                    let isPicked  = $(oTable.row(dataIndex).node()).attr('data-picked-row')  == 1;
                    let isReady   = $(oTable.row(dataIndex).node()).attr('data-fully-ready') == 1;
    
                    // rows to keep - all tests must pass to keep this row
                    if (
                        // Test 1 - Hide Picked Checkbox
                        ( (hidePickedRecords && !isPicked) ||
                          (! hidePickedRecords) )
                        &&
                        // Test 2 - Hide Unready Checkbox
                        ( (hideUnReadyRecords && isReady) ||
                          (! hideUnReadyRecords) )
                      ) {
                        return true;
                    }
    
                    // otherwise filter out this row
                    else {
                        return false;
                    }
            });
        }
    
  • allanallan Posts: 63,522Questions: 1Answers: 10,473 Site admin

    Nice one - thanks for sharing your solution with us.

    Allan

This discussion has been closed.