You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I've searched the TanStack documentation, and the codebase, and the discussion forums, and GitHub, and Google, and not been able to locate an example yet, so here goes... apologies in advance for the long post (buckle up), I'm aiming for clarity over brevity here...
I am looking to implement something roughly like "boolean logic" in a global filter. In my mind this might look a bit like a SQL WHERE clause, except that each term would be checked across the entire row (at least every column that allows global filtering, because it's a global filter) rather than applying the whole filter column-by-column. It might also look a bit like a simple Google search, however I'm not suggesting that the full set of Google Search operators needs to be implemented... but as a bare minimum some truly-global equivalent to AND and OR operators would be useful.
How it behaves today
Picking the existing React Filter Example just as a starting point for comparison (and only adjusting the data, not the filter logic) it has a "fuzzy" search implemented. This returns some interesting results, for example:
It is curious that the global filter term foo ba somehow matches "fooblarg" (I assume because it is fuzzy it is effectively searching for each character of the filter value in order left-to-right, allowing other characters to exist in between). Not something I would've expected in my desired filter implementation, but hey I guess that's the fuzzy part of this one so that's understandable in this case, and at least it can match across (multiple) word boundaries.
However - note that it doesn't split the filter string into independent tokens (ie. it must be left-to-right, it doesn't match "bar foo").
Note also that it can still only apply this logic to one single cell at a time, in order to determine whether that row passes the filter or not (ie. it does not include rows that have "foo" in one column and "bar" in a different column). This is enforced by the FilterFn interface in Tanstack Table which takes a single columnId. This implies the calling code iterates over each column in a row, and checks the global filter once for each column. Inspecting with breakpoints confirms that this is indeed how global filters are applied.
Getting close
It's easy enough to build a global filter that can implement boolean logic within a single column. Here's OR:
Note that for OR, if any single cell matches (passes the filter) then by definition that whole row should be shown (it's OR, not XOR). Therefore for OR, looking at one cell at a time is actually good enough to make it work correctly at a global level too. Yay!
Notice that unlike the original/unmodified fuzzy matching, the order no longer matters... "foo bar" and "bar foo" are just as valid as each other, as long as both terms are still within the same cell. That's fine, and expected. Another Yay!
The issue is that we ultimately show the user the entire row, but we actually only apply the filter to each cell one-at-a-time. We want this to be a truly global filter. That means it should match any row where that row contains each term can be in any of it's cells, ie. it should also match across columns like this:
It seems like it will be difficult (impossible?) to implement this AND logic when the current TanStack Table code is applying the global filter column-by-column, one column at a time.
Finally getting to the question
Has anyone seen a working implementation/example of a global filter that implements logic like AND and OR across all columns (ie. truly global, not per-column)?
If not, does anyone have any thoughts on how it could be implemented using the current (v8) TanStack Table (if it is even possible)? Is there maybe a way of tracking intermediate match-state for each token from column to column (maybe with Meta, or some utility library I haven't discovered yet?) so filter logic could still achieve a global AND, even if it is sill applied column-by-column?
If not, is it something worth getting on the Roadmap (perhaps for v9)?
The TanStack Table code shouldn't need to care what the actual syntax is, but it does need enough support to allow global filters to operate across columns. I don't really care what the format of the input string is, tokenising that within a filter should be easy enough... eg. any of the following could reasonably be essentially equivalent:
AND: foo AND bar foo & bar foo bar (assuming an implicit AND between words here, more similar to a Google search than SQL-ish)
OR: foo OR bar foo | bar
Bonus question / Future Feature request
Not specifically required for my immediate needs, but for completeness... Has anyone seen (or feel like implementing as a challenge):
Let's throw in a NOT operator, eg. NOT foo as a global filter would return all rows where "foo" does not occur (in any eligible column). This one likewise needs to be applied across all (eligible) cells in a row, because currently if one cell passes a NOT filter then it marks the filter as passed and includes the row (even if one of the other cells in the row means it should fail the filter).
Grouping, to allow for compound filters. Imagine a global filter like (foo AND bar) OR (blarg AND NOT wibble) grouped in this case by parentheses. TanStack Table shouldn't need to care about the syntax (that's the job of whoever implements the filter code) but ideally it would have enough support to apply global filters across all (eligible) columns, accounting for cases such as this that may have structured groups (potentially nested arbitrarily deep, not just a flat array) and a mix of operators.
For extra credit, include multiple types of matching logic "primitives" within a single filter, such as differentiation between exact/partial match. For example, imagine a global filter implementation like foo AND "bar bar" where in this case the syntax implies partial match (includesString) by default, and quote marks mean an exact match (equalsString). Again, TanStack Table shouldn't need to care about the syntax (that's the job of whoever implements the filter code) but ideally it would have enough support to allow implementation of a compound global filter like this, with heterogeneous primitives.
A nasty hack
So... I could just add an "everything" column to the table, which contains all values for the entire row concatenated... and then hide that column visually, and then only apply the global filter to that one column. Functionally that could work, but for a table with 60+ columns that just feels nasty (double the data? double the memory?). Also concatenation would break future extension options for non-string primitives (eg. numerical values less than X or whatever). Plus it risks false positives if a single token matches across a concatenated column boundary, depending on how the concatenation is implemented. There must be a better way.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
I've searched the TanStack documentation, and the codebase, and the discussion forums, and GitHub, and Google, and not been able to locate an example yet, so here goes... apologies in advance for the long post (buckle up), I'm aiming for clarity over brevity here...
I am looking to implement something roughly like "boolean logic" in a global filter. In my mind this might look a bit like a SQL WHERE clause, except that each term would be checked across the entire row (at least every column that allows global filtering, because it's a global filter) rather than applying the whole filter column-by-column. It might also look a bit like a simple Google search, however I'm not suggesting that the full set of Google Search operators needs to be implemented... but as a bare minimum some truly-global equivalent to AND and OR operators would be useful.
How it behaves today
Picking the existing React Filter Example just as a starting point for comparison (and only adjusting the data, not the filter logic) it has a "fuzzy" search implemented. This returns some interesting results, for example:
foo ba
somehow matches "foo blarg" (I assume because it is fuzzy it is effectively searching for each character of the filter value in order left-to-right, allowing other characters to exist in between). Not something I would've expected in my desired filter implementation, but hey I guess that's the fuzzy part of this one so that's understandable in this case, and at least it can match across (multiple) word boundaries.Getting close
It's easy enough to build a global filter that can implement boolean logic within a single column. Here's OR:
Note that for OR, if any single cell matches (passes the filter) then by definition that whole row should be shown (it's OR, not XOR). Therefore for OR, looking at one cell at a time is actually good enough to make it work correctly at a global level too. Yay!
...but no cigar
Now, let's take a look at a corresponding AND:
This will work for AND within a single cell:
Notice that unlike the original/unmodified fuzzy matching, the order no longer matters... "foo bar" and "bar foo" are just as valid as each other, as long as both terms are still within the same cell. That's fine, and expected. Another Yay!
The issue is that we ultimately show the user the entire row, but we actually only apply the filter to each cell one-at-a-time. We want this to be a truly global filter. That means it should match any row where that row contains each term can be in any of it's cells, ie. it should also match across columns like this:
It seems like it will be difficult (impossible?) to implement this AND logic when the current TanStack Table code is applying the global filter column-by-column, one column at a time.
Finally getting to the question
The TanStack Table code shouldn't need to care what the actual syntax is, but it does need enough support to allow global filters to operate across columns. I don't really care what the format of the input string is, tokenising that within a filter should be easy enough... eg. any of the following could reasonably be essentially equivalent:
AND:
foo AND bar
foo & bar
foo bar
(assuming an implicit AND between words here, more similar to a Google search than SQL-ish)OR:
foo OR bar
foo | bar
Bonus question / Future Feature request
Not specifically required for my immediate needs, but for completeness... Has anyone seen (or feel like implementing as a challenge):
Let's throw in a NOT operator, eg.
NOT foo
as a global filter would return all rows where "foo" does not occur (in any eligible column). This one likewise needs to be applied across all (eligible) cells in a row, because currently if one cell passes a NOT filter then it marks the filter as passed and includes the row (even if one of the other cells in the row means it should fail the filter).Grouping, to allow for compound filters. Imagine a global filter like
(foo AND bar) OR (blarg AND NOT wibble)
grouped in this case by parentheses. TanStack Table shouldn't need to care about the syntax (that's the job of whoever implements the filter code) but ideally it would have enough support to apply global filters across all (eligible) columns, accounting for cases such as this that may have structured groups (potentially nested arbitrarily deep, not just a flat array) and a mix of operators.For extra credit, include multiple types of matching logic "primitives" within a single filter, such as differentiation between exact/partial match. For example, imagine a global filter implementation like
foo AND "bar bar"
where in this case the syntax implies partial match (includesString
) by default, and quote marks mean an exact match (equalsString
). Again, TanStack Table shouldn't need to care about the syntax (that's the job of whoever implements the filter code) but ideally it would have enough support to allow implementation of a compound global filter like this, with heterogeneous primitives.A nasty hack
So... I could just add an "everything" column to the table, which contains all values for the entire row concatenated... and then hide that column visually, and then only apply the global filter to that one column. Functionally that could work, but for a table with 60+ columns that just feels nasty (double the data? double the memory?). Also concatenation would break future extension options for non-string primitives (eg. numerical values less than X or whatever). Plus it risks false positives if a single token matches across a concatenated column boundary, depending on how the concatenation is implemented. There must be a better way.
Beta Was this translation helpful? Give feedback.
All reactions