Deactivating filter button does not reset search filter
Deactivating filter button does not reset search filter
trongart
Posts: 222Questions: 51Answers: 0
In this test case, I am trying to trigger the .filter button at table load with:
table.button('.filter').trigger();
or with
initComplete: function () {
this.api().button('.filter').trigger();
}
For both cases, the button is activated correctly when the table loads, but when I deactivate the button, the search filter is not reset. What could be missing here?
This question has accepted answers - jump to:
Answers
you are popping the search plugin. You need to follow that with calling
draw()
for Datatables to update the table filtering.Kevin
@kthorngren yes when the
filter
button is deactivated withthis.active(false)
so that the search plugin is popped with$.fn.dataTable.ext.search.pop()
, the last action element isdt.draw()
which should update the table filtering, but it does not do that for some reason.I added another test case with a reset button that clears all search filters and redraws the table and it does not work here either. Somehow table
draw
is not triggered at all.I added some console.log debug statements to look at what is happening. When the button is clicked and active you can see there are to search plugins; the first is yours and the second is from the SearchBuilder:
When you are popping the plugin added by the SearchBuilder is removed.
Because its hard to control I don't pop the search plugins. Instead I just add them before Datatables initialization and use if statements in the plugin function to determine if the plugin code should be executed. Basically you would check to see if the button is active. If not the simply `return true;`` otherwise execute the code in the function.
http://live.datatables.net/rawanise/2/edit
Kevin
@kthorngren Thank you so much for looking into this.
Not sure why
.draw
does not simply reset everything here.My understanding was that with
table.button('.filter').trigger()
the button function checks if the button is active as it's in the function. How would you add the relevant check before Datatables initialization with if statement in the plugin function to determine if the plugin code should be executed? I think it is the same issue in your test case as well.See this example:
http://live.datatables.net/rawanise/4/edit
Kevin
@kthorngren This is excellent- thank you so much for your help!!!
Don't try setting the attributes in the search plugin as it will execute once for each row. In this case you will set the CSS 57 times.
In the button action function go back to using the if statements you had before. Toggle the state and set the CSS but remove the plugin push and pop.
Kevin
@kthorngren You are right- The CSS gets executed 57 times in the search plugin which is not ideal.
I've gone back using the if statements without pop and push as you suggested for the CSS and added the state toggle, but something is not working here.
You need to remove the statement that is toggling the state since you are also toggling the state in the if statements. Remove this:
http://live.datatables.net/perohovi/2/edit
Kevin
Yes this is perfect. Thank you so much Kevin!
In my project I use the buttons as in this test case. It has 3 buttons, there is a global variable
global_index
that saves each index and then when a button is deactivated I use.fn.dataTable.ext.search.splice
of the index to remove the specific filters. This way not all search filters are removed and I can activate the filters in different sequences while turning them off one by one. This has wroked fine until it stopped when I used a button trigger such astable.button('.filter').trigger()
after table load (original issue of this thread).In the test case I left the original code with
$.fn.dataTable.ext.search.push
inside the if statements of every filter but commented it out as we moved it now to before Datatables initialization so I now applied what we found here to my test case. However, only the first filter button seems to work here.The problem is you are removing the plugin with
$.fn.dataTable.ext.search.splice(global_index.indexOf($('.filter2').index()), 1);
. Remove these statements. Updated example:http://live.datatables.net/vogasofu/2/edit
Kevin
@kthorngren Again thank you so much for your help here! Your feedback is absolutely invaluable!
This works correctly, but when I applied this to my project with 9000 rows and 30 buttons, I got a huge performance decrease by moving
$.fn.dataTable.ext.search.push
outside of Datatables initialization. A button click that took almost an instant to filter the table, now takes 6 seconds so this would not be a solution.Not sure what I can do here except for simply not using button triggers on table load at all (and with it would not be able to use stateSave on button as triggering them leads to the main issue of this thread). This is the button configuration that worked without
$.fn.dataTable.ext.search.push
outside of Datatables initialization.I see two choices:
Restructure the code so you have only one search plugin, like this:
http://live.datatables.net/vogasofu/5/edit
Use your push / pop method. The problem is, now you need to worry about SearchBuilder adding search plugins. You may need to add more logic to keep track of where the SearchBuilder plugin is in array. Not sure how to do this. One of the developers may have some ideas for you.
Possibly you can use array.splice() to insert the plugins in the same spot in the array. For example
.filter
is always the first position,.filter2
is the second, etc. This way you won't affect what other plugins add.Kevin
Thank you @kthorngren
Works, but decreases performance 5-6x for larger datasets with lots of buttons.
This might work, but not sure where to start.
Would appreciate any input from the developers. Ideal case would be if I could simply trigger/activate a button just like a click on an already loaded table based on stateSave.
Here is a complete test case with stateSave and button saving/triggering. The issue here is that once you click on Filter1 button for example and reload the table - yes, Filter1 button loads as that gets saved and triggered, but once you deactivate it, the table does not get reset and using method 1 by @kthorngren as above decreases performance considerably.
I was thinking of something like this even:
jQuery(function(){
jQuery('.filter1').click();
});
But same issue. Is there a way to click the buttons after everything is fully loaded based on those buttons that need to be triggered from stateSave as in my testcase?
The problem is the same as I described before. You are removing the SearchBuilder plugin and not the one for the inactive button so the filter is still active when you don't expect it to be. I added a console.log into a
draw
event function so you can see this.http://live.datatables.net/kebubiho/2/edit
Start the page with no filters active. Activate 1 and 2. and look at the output. You will see three plugins in the array. Reload the page then deactivate filter 1. You will see 2 plugins in the array but the table hasn't changed because the wrong plugin was removed. Deactivate the other filter and still the table hasn't changed and you will see the SearchBuilder plugin was removed (the one with the
(e,f,g)
parameters. Now the SearchBuilder doesn't work either. You can see this by trying to apply the filter Position > Not > Accountant.Kevin
Thinking about this for a bit you will need to trigger the active buttons after
initComplete
and after SearchBuilder has added its plugin. Looks like after the SearchBuilder is initialized it callsdraw()
. You can instantiate thedraw
event ininitComplete
using jQuery one() instead of on() so it runs once. If the length of the search plugin array 1 or more, then you can trigger the active buttons. After that the array splicing you are doing doesn't seem to affect the SearchBuilder plugin.http://live.datatables.net/jinuroje/1/edit
I'll leave it yo you to test and make sure it works properly.
Kevin
@kthorngren I must say that this is absolutely genius and yes it works as intended! Thank you so much again. Your help and feedback have been extremely invaluable!!
One small thing: I do not want to save the searchBuilder with stateSave and I do this by adding
delete data.searchBuilder;
intostateLoadParams
, but doing so breaks this approach as filter buttons are no longer saved. Is there maybe an alternative way to not load searchBuilder?Test case with
delete data.searchBuilder;
.Looks like deleting the searchBuilder object causes searchBuilder to not execute the initial draw so the
draw
ininitComplete
doesn't execute when expected. If you investigate what searchBuilder saves with an empty search you will see its{}
. Settingdata.searchBuilder = {};
instead of deleting it seems to work.http://live.datatables.net/gaduneva/1/edit
This likely means that if you disable SearchBuilder then you will need to remove the
draw
ininitComplete
for your solution to work properly.Kevin
Thank you so much Kevin!!! Have a nice weekend