Custom Numeric Filter Function is not working as expected


#1

Hello,

I’m currently trying to integrate a custom filter function to handle numeric filtering.

The default #numeric_filter tool is not working - most likely do to some customization other developers on my team did to the library. FYI, we are using an older version of DHTMLX (3.5). Note, using this older version does not affect the usability of the grid.

The interesting part:
I’ll first show you the method that I’ve written to handle numeric filtering. Then I’ll describe the issues I am having.

Note - gridtable is the name of my grid.
Note - The input field has been created using attacheHeader method and including #numeric_filter. That being said, I am accessing the input an trying to write my own function. I am considering that this might be a source of the issue, but since the function is custom, I do not think this is the source of the issue.********

What the function is doing - it should take the input in the first column and perform the filter function on it.

    gridtable.getFilterElement(0)._filter = function(){
      var input = this.value; // gets the text of the filter input
      
      let operator = input.match(/>=|<=|>|</);
      var number = input.match(/\d+/g);

      // If operator is null and there is a number, return the number
      if (!operator && number) {
        gridtable.filterBy(0,function(a){ return (a == number);}, true); 
      }

      if (operator) operator = operator[0];
      number = parseInt(number);

      if (operator && number) {
        switch(operator) {
          case ">=": 
            gridtable.filterBy(0,function(a){ return (a>=number);}, true);
            break
          case "<=":
            gridtable.filterBy(0,function(a){ return (a<=number);}, true); 
            break
          case ">":
            gridtable.filterBy(0,function(a){ return (a>number);}, true); 
            break
          case "<":
            gridtable.filterBy(0,function(a){ return (a<number);}, true); 
            break
        }
      }
          
      return
    }

Issues I am having:
Problem 1. Just including this function does not cause the filter function to occur when a user enters a value. I need to include an empty event handler above it. It is not clear to me why this is needed to yield a result, considering that the event handler function is empty.

gridtable.attachEvent("onFilterStart", function(ind, val) {

});

Once the above event handler has been included, I am able to return a first result - for example, if the grid has 50 rows and numbers 1-50 in the cells, and my input is ‘>10’, the grid will yield 11-50. This works, but then:

Problem 2:
If I then try clear the field to show all results again - it is not clear to me how to do that. I tried using the ‘onFilterEnd’ event handler, but it doesn’t fire when I empty the field.

Problem 3:
If I try to search for an item in the grid which is 10 or less, I get the error “Cannot read properties of undefined (reading ‘idd’)”. Tracing this error down takes me to the library code, which from my understanding should not be an issue since I am writing a custom function - not using the #numeric_filter filtering method. Recall the note from above (***********). Might this still be calling the library, even if there is a custom function written?

I’ve written the following function to handle numeric filtering

Problem 4:
It is not clear to me how combo filtering is meant to work. You’ll notice in the code above, I added a 3rd parameter (true) [ gridtable.filterBy(0,function(a){ return (a>=number);}, true);] My understanding is that adding true to a filterBy method allows combo filtering to work - though I admit it is not clear to me how.

Any support is welcome, thank you.


#2

Could you please, clarify what do you mean under that, as the numeric_filter working well for me locally.
You can check it in the online sample:
https://dhtmlx.com/docs/products/dhtmlxGrid/samples/08_filtering/03_pro_filter_num.html

Also, your custom function is completely incorrect, as you don’t need to use the filterBy() method inside it.
You can check in the original tutorial:
https://docs.dhtmlx.com/grid__filtering.html#redefiningdefaultfilterlogic
that returning true/false from the _filter() function will filter the record. Because the _filter function iterates through all the records of your dataset and you just need to signalize if this record suits your filtering logic or not. Just like the common JS filter function:


#3

Hello,

“Could you please, clarify what do you mean under that, as the numeric_filter working well for me locally.
You can check it in the online sample:”

  • As I mentioned above, the numeric filter is not working. I believe the reason for this is because the library we have in the codebase has been customized.

Current problem
URL: https://docs.dhtmlx.com/grid__filtering.html
Quote from that URL: " Any filter you assign to the grid (both by adding it to the header and by creating through the makeFilter() function) can use a custom logic instead of the default one."
The quote above does not seem to be working as described. I created custom functions, yet I am still getting errors that are coming from the library in the areas where the default logic for #numeric_filter is.


#4

Hello akalimi.

Current problem
URL: https://docs.dhtmlx.com/grid__filtering.html
Quote from that URL: " Any filter you assign to the grid (both by adding it to the header and by creating through the makeFilter() function) can use a custom logic instead of the default one."
The quote above does not seem to be working as described. I created custom functions, yet I am still getting errors that are coming from the library in the areas where the default logic for #numeric_filter is.

According to your provided code you are not using a typical html-input with the makeFilter() logic assigned to it, but a “non-working” numeric filter with the redefined logic according to the following guide:
https://docs.dhtmlx.com/grid__filtering.html#redefiningdefaultfilterlogic
so the linked tutorial is not related to your provided code snippet.
If the problem still occurs or you please, provide a complete demo, where your case could be tested


#5

Hi,

Let me walk you through my updated setup.

Please note I am using v3.5

  1. This is the setup for how the headers are being created. Notice that I previously used the #numeric_filter code to add the built in numeric filter - that has been replaced with an input with the id ‘numericFilter’.

  2. This is the filter in the grid (the first column)

I have written my comments and questions into the codeblock as comments below. The key questions are comments 3,4,5,6,8. Once this is clear, I am hoping the filtering works.

   // 1 - turn the input into a filter
  gridtable.makeFilter("numericFilter", 0)
  // 2 - custom function which mimics the functionality of #numeric_filter
  gridtable.getFilterElement(0)._filter = function() {
  let input = this.value;
  let operator = input.match(/>=|<=|>|</);
  var number = input.match(/\d+/g);

  if (operator) operator = operator[0];
  number = parseInt(number)

  // if (!operator && number) {
  //   // 3 - What should I use to return only the rows which match the input number if there is no operator?
  //   // 4 - What would I use instead of the filterBy method?
  //   gridtable.filterBy(0,function(a){ return (a == number);});
  // }
  if (input == "" || input == " ") {
    console.log("blank");
    gridtable.filterBy(0,"");
  } 
  
  // 5 - Should I be iterating through the grid like so here? I would assume so since the value of the cell needs to be converted to a number.
  for (var i=0; i<gridtable.getRowsNum(); i++){
    let cellVal = parseInt(gridtable.cellByIndex(i,0).getValue(i)); // i - the index of a row in the grid
    if (!operator && number) {
      // 5 - What should I use to return only the rows which match the input number if there is no operator?
      // 6 - What would I use instead of the filterBy method?
      // 7 - The line below works to return the cases that match. The line below that does not.
      // gridtable.filterBy(0,function(cellVal){ return (cellVal == number);}); <---- This works to filter the grid and show the elements that I want to show.
      // return cellVal == number; <--- this does not work to return the rows of the grid that I want to show.
    }

    // 8 - How should I handle the different cases below to return rows that meet search criteria if I should not use the filterBy method?
    if (operator && number)
    switch(operator) {
      case ">=": 
        // gridtable.filterBy(0,function(cellVal){ return (cellVal>=number);}); <--- this works to return the cases that match
        // return (cellVal>=number); <-- this does not work to return the cases that match
        // break
      case "<=":
        // gridtable.filterBy(0,function(cellVal){ return (cellVal<=number);}); <--- this works to return the cases that match
        // return (cellVal<=number); <-- this does not work to return the cases that match
        // break
      case ">":
        // gridtable.filterBy(0,function(cellVal){ return (cellVal>number);}) <--- this works to return the cases that match
        // return (cellVal>number); <-- this does not work to return the cases that match
        // break
        case "<":
        // gridtable.filterBy(0,function(cellVal){ return (cellVal<number);}); <--- this works to return the cases that match
        // return (cellVal<number); <-- this does not work to return the cases that match
        // break
    }
  }
};

The next step here is understanding how to make sure all of the column filters work together to further narrow down results. What do I need to do to ensure that works?

Warmly,
Adam


#6

Hello,

When you have a chance can you reply to my post above.

Thank you!


#7

you don’t need to use the filterBy() method inside it.
You can check in the original tutorial:
https://docs.dhtmlx.com/grid__filtering.html#redefiningdefaultfilterlogic
that returning true/false from the _filter() function will filter the record. Because the _filter function iterates through all the records of your dataset and you just need to signalize if this record suits your filtering logic or not. Just like the common JS filter function.
Your original function will look something like:
https://snippet.dhtmlx.com/5/9d82e5a40