Custom filtering - why is my filter not being cleared?
Custom filtering - why is my filter not being cleared?
Hello,
I have an annoying issue, which I cant solve, and hope you can give me a few hints.
I am trying to implement the range search, as in the example here:
https://datatables.net/examples/plug-ins/range_filtering.html
My function also includes some cases with different result.
e.g. if * is entered, all rows with data in the field is shown.
If ? is entered, all rows without data in the field is shown.
If test is entered the result is filtered as default.
If I delete a char / text from the input, the search / filter is automatically refeshed ,as expected.
It works all good.
My issue is, that I have made a case, where, if I enter : is should list values within a given rage, exactly as in the given example. The filter works, and only a few rows with the range is listed.
But if I delete the filter (:) the filter is not cleared, and the rows remain as if the filter was on. It works differently as the * and ? cases.
If I enter * afterwards, the new filter is activated.
If I delete the char : from the input I actually never reach scope (only if I have used another filter prior to the : )
if((this.value == null) || (this.value == "") || (this.value == undefined))
Why do I see this behavior - why is the filter not cleared if I remove the : / leave the case, just as it is the case with the ? and *
I think I have tried many things, but I cant get the specific filter to work. Any hints - do a filter wrong, do I redraw wrong, or is my code which is pure garbage..
Regards, K
$('#myTable').DataTable().columns().every( function ()
{
let that = this;
$( 'input', this.footer() ).on( 'keyup change', function () {
columnIdx = that[0];
if ( that.search() !== this.value )
{
if((this.value == null) || (this.value == "") || (this.value == undefined))
{
console.log("this.value == null");
that.search( '(?=.*)', true, false ).draw();
}
else {}
input = this.value;
input = input.trim();
if(input.indexOf('+') >= 0)
{
console.log("Ignore filter: " + input);
}
else if(input.indexOf('*') == 0)
{
regex = '^(?!\s*$).+';
console.log("Filter: " + regex);
that.search( regex, true, false ).draw();
}
else if(input.indexOf('?') == 0)
{
regex = "^\s*$";
console.log("Filter: " + regex);
that.search( regex, true, false ).draw();
}
else if(input.indexOf(':') == 0)
{
console.log("::::");
$.fn.dataTable.ext.search.push(
function( settings, data, dataIndex )
{
var min = 50; //parseInt( $('#min').val(), 10 );
var max = 1000; //parseInt( $('#max').val(), 10 );
var age = parseFloat( data[columnIdx] ) || 0; // using the data from the 4th column
if ( ( isNaN( min ) && isNaN( max ) ) ||
( isNaN( min ) && age <= max ) ||
( min <= age && isNaN( max ) ) ||
( min <= age && age <= max ) )
{
return true;
}
return false;
});
table.draw();
}
}
} );
} );
Answers
We're happy to take a look, but as per the forum rules, please link to a test case - a test case that replicates the issue will ensure you'll get a quick and accurate response. Information on how to create a test case (if you aren't able to link to the page you are working on) is available here.
Cheers,
Colin
Hi Colin,
sure, I have tried to simplify the code and made it availble.
Its founds here:
https://live.datatables.net/jumupiko/13/edit?js,console,output
To reproduce the issue:
Enter "c" in search field for column Name (result: 24 out of 57)
Enter "c" in search field for column Position (result: 18 out of 57)
Delete "c" in search field for column Name (result: 35 out of 57)
Enter "c" in search field for column Name (result: 18 out of 57)
Enter "*" in search field for column Age (result: 5 out of 57) (all 5 within the specified age range)
So far so good...
Delete "c" in search field for column Name (result: 10 out of 57) (all 10 within the specified age range)
Enter "c" in search field for column Name (result: 5 out of 57) (all 5 within the specified age range)
Delete "*" in search field for column Age
... And this is where it breaks. The search result is not adjusted and redrawn.
What is it I missing - do I need to pop something... Or am I completely missing some understanding in my code to achieve what I am trying to?
The biggest issue is that you are calling the function
ageRange()
each time the*
is the first character in the Age input. This is pushing a new copy of the search plugin to the search stack. After typing*
five times as the first character you will have 5 copies of the search plugin running. You could push and pop but if you have multiple plugins running it would be problematic.One option is to use a flag variable to keep track of whether to run the plugin code or not. Check the flag in the plugin.
Another problem is you are doing this comparison:
Since you aren't using
column().search()
when*
is the first character this comparison doesn't work. The code needs to be refactored a bit. See this example:https://live.datatables.net/jumupiko/14/edit
I didn't fully test it. Will leave that to you but it should give you an idea of how this should work.
Kevin
Many thanks Kevin,
appreciated!
I follow you with the flag to keep try on the filter. I will work on that one. After your example, I have tried many possible solutions, but none of them are working so far, but am sure it will suddenly come.
In your example, it seems the behavior is pretty much the same as where I started...
The columns can be searched with free text, except the Age column. It only takes the *, and it is not possible to search for a single number from with within the list. No result is being displayed in that case.
See if this works better. Changed this section of code:
https://live.datatables.net/jumupiko/16/edit
Kevin
Thanks Kevin!
It was a good hint.
I have changed the flag to use an array instead, which holds the individual flags based on the used columns searched. This allow to keep try on all the pushed apis. I also dont have to code the ID name from the search field, as I can get it dynamically with the column / index.
Again, many thanks!