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
{{ message }}
Repository navigation
[v8] Global filter gives TypeError: l.toLowerCase is not a function when using number fields #4280
With latest 8.5.11 version using the Global filter in combination with number fields gives:
Note this was already raised in #4210 but still happens with latest version unfortunately.
I think this was introduced somewhere in 8.3.x line as I first encountered this while upgrading from 8.2.x to 8.3.3.
A workaround like
{
id: 'matches',
header: 'Matches',
accessorFn: (originalRow) => originalRow.matches.toString(), // matches is a number
// accessorKey: 'matches', // this worked before
},
seems to work for the filtering, but this would also impact the sorting I would assume. Sorting on a string value instead of the number value will have impact (1, 2, 10 vs 1, 10, 2).
Your minimal, reproducible example
.
Steps to reproduce
See above.
Expected behavior
Global filter to work with number fields out of the box.
How often does this bug happen?
Every time
Screenshots or Videos
No response
Platform
macOS, chrome
react-table version
v8.5.11
TypeScript version
4.7.4
Additional context
If reproducible example is needed let me know.
Terms & Code of Conduct
I agree to follow this project's Code of Conduct
I understand that if my bug cannot be reliable reproduced in a debuggable environment, it will probably not be fixed and this issue may even be closed.
Reacted by sean-esper, Benjamin Merchin, Alex Crețu, Seth Coussens, Wendy Cheung, Francis Lavoie, Ofek Asido, aranya-danno, mahdi1696, Kasey Culmback and 19 more
Reacted by Tim Basel
Reacted by Matthew Torgerson, Rauf, Seth Coussens, Ofek Asido, Omer Elbaz, Carlos Vieira, Loïc, Tim Basel and 0Chan-smc
The above error occurred in the component
... stack trace
React will try to recreate this component tree from scratch using the error boundary you provided, ErrorBoundary.
I am so novice on this. I copied the includesString built-in function and converted the value to string. And now use that as the globalFilterFn.
Do you think it could be useful?
function testFalsey (val: any): boolean {
return val === undefined || val === null || val === ''
}
export const includesString: FilterFn<any> = (
row,
columnId: string,
filterValue: string
) => {
const search = filterValue.toLowerCase()
// Convert to String
const value = String(row.getValue<string>(columnId))
return value?.toLowerCase().includes(search)
}
includesString.autoRemove = (val: any) => testFalsey(val)```
Reacted by oldo.nicho, a-yamaneki, AgkTF and Jellow
Reacted by Lautaro Riveiro, Wendy Cheung, Ofek Asido, Filip Malinowski, Omer Elbaz and anolan23
Reacted by Daniel Bayerlein, Maxime Antoine, AgkTF, Sarah So, Meyer Attal, Harman Pannu, Pierre Cholhot, Lucas Pereira de Souza, Simon Cardona, Amr Hany Saleh and 8 more
@decayedCell unfortunately that is not really a fix when having a global filter in the first place 😉
Not sure what you mean by this. I have ran into the same issue, I have 2 tables and both use global filter and a search component that sets the global filter. For the table that only has strings as fields there are no issues, but on the other one I ran into the same issue mentioned by you. So I disabled GlobalFilter for only that column that uses numbers and now I have no issues using my search component. Obviously the negative is that that number column is completely ignored now, but until a fix it makes the table not crash at least while still providing the global filter functionality for the other columns.
@marceloverdijk while this doesn't solve whatever the underlying issue in the code is... you can follow one of the examples to implement a fuzzy filter that replaces the global and seems to work fine.
I took a page from @LautaroRiveiro suggestion by overriding the globalFilterFn, but instead of casting all values as a String I do a check on whether the field is a number, and if so only then make a conversion to a string:
const globalFilterFn: FilterFn<T> = (row, columnId, filterValue: string) => {
const search = filterValue.toLowerCase();
let value = row.getValue(columnId) as string;
if (typeof value === 'number') value = String(value);
return value?.toLowerCase().includes(search);
};
Reacted by Muhammad Bilal Afzal, Matt Przybylski, Oscar Penut, Rahul Pratap, Petko Bonev, Carlos Vieira, Costa Alexoglou and Stward Pérez
Reacted by Carlos Vieira, Costa Alexoglou and Pasha Suprunchuk
I think the reason why this is happening is because of the following commit: a5578ac
The default behavior of getColumnCanGlobalFilter will now return true for any columns that are either string or number, but the default filter functions don't have the same flexibility. So the various options for working around the bug are as follows:
Change all your columns to string type
Use your own filter function which allows either string or number type
Override getColumnCanGlobalFilter in your table options so that it goes back to old behavior of only returning true for string type columns
I also hit this problem from a different direction - I wanted to filter on string array type columns - which is possible to do if you have a flexible filter function that handles array types - but that column would never appear because getColumnCanGlobalFilter filtered it out.
I think there are three things that could happen going forward, assuming the goal is that global filters should be type-flexible in the default case.
Provide a convenient factory function that can create a getColumnCanGlobalFilter function based on supported types (i.e. we should be able to specify which types we want to allow for a particular table without having to override the entire function supplied in default filter options)
There should be a type-flexible version of includesString which can at least handle all of the types allowed by getColumnCanGlobalFilter, or even better handle any type thrown at it by stringifying it
I also noticed if you don't supply a globalFilterFn it defaults to "auto", which I guess is supposed to figure out the correct filter to use depending on the column type and avoid the user having to do any of this complicated setup themselves, but in my case that's not working either, because it decides to use includesString for a number column.
Reacted by Carlos Vieira, Muhammad Hasbi and Eiko Wagenknecht
The same issue. I use the latest version "@tanstack/react-table": "^8.5.22";
I am getting TypeError: o.toLowerCase is not a function when I use the globalFilter feature which is basic one and is not fuzzy implementation.
There are one number-type data column, two string-type data columns and a number of display columns in my Table definition. (There is no group header)
If I remove the sole number-type data column, the table does not render at all having the same error.
If I keep the number-type data column, I receive the error when I type the input field which is debounced input related with globalFilter as it is in the examples in the tanstack web site.
I get the same "o.toLowerCase is not a function" error when I have a number-type column, even on latest v8.5.27 released today.
I solved it by simply adding .toString() on the number column's accessorFn.
While the solution is quite simple, it was not easy to understand and I hope it'll be fixed soon, or at least have better error handling so developers will have a better idea of what to do in this situation.
Reacted by oldo.nicho, Tomé de Oliveira, Neal Stanard, Muhammad Hasbi, mosudev, Lukas Jakob Hafner, Oluwaseye, Carretta Riccardo, Ozair, vonZ and 1 more
Reacted by Harman Pannu, lobaak, Matt Wood, Yasser Alsaidi, Melih Yumak, Adeel Ali, Alvaro Martinez, chan, Charlie Carr, Hanip Alhapidz and 19 more
Reacted by Stward Pérez, lobaak, Matt Wood, Aikins Laryea, Alvaro Martinez, Nicholas Hamilton, Kamal Berrada, Charlie Carr, Xander Knox, Hanip Alhapidz and 11 more
I was working with date and numeric columns
The accessorFn used would return number or dates or undefined depending on the column. This would then make the native sorting functionality to work
The column's cell function would then format the numbers or dates for rendering
I noticed that the globalFilterFn was ignoring these specific fields when I debugged my code
To solve this, I had to
format the date and amount values to string as the return value of the accessorFn
Create custom sortingFn for the respective columns and access the raw value from Row data
Activity
dimbslmh commentedon Aug 9, 2022
Experiencing the same issue in v8.5.11.
The following is shown in Console:
Things I've tried:
LautaroRiveiro commentedon Aug 12, 2022
I am so novice on this. I copied the includesString built-in function and converted the value to string. And now use that as the globalFilterFn.
Do you think it could be useful?
decayedCell commentedon Aug 18, 2022
As a temporary fix I added
To my number column
marceloverdijk commentedon Aug 18, 2022
@decayedCell unfortunately that is not really a fix when having a global filter in the first place 😉
decayedCell commentedon Aug 18, 2022
Not sure what you mean by this. I have ran into the same issue, I have 2 tables and both use global filter and a search component that sets the global filter. For the table that only has strings as fields there are no issues, but on the other one I ran into the same issue mentioned by you. So I disabled GlobalFilter for only that column that uses numbers and now I have no issues using my search component. Obviously the negative is that that number column is completely ignored now, but until a fix it makes the table not crash at least while still providing the global filter functionality for the other columns.
marceloverdijk commentedon Aug 18, 2022
Exactly what I meant, the column is completely ignored and that's not what I want
jeg924 commentedon Aug 22, 2022
@marceloverdijk You can keep the data types intact and just pass in sanitized tableData before you initialize the table like this:
It's not as pretty as just passing in
datatouseReactTablebut it will solve your problems.scoussens commentedon Sep 1, 2022
@marceloverdijk while this doesn't solve whatever the underlying issue in the code is... you can follow one of the examples to implement a fuzzy filter that replaces the global and seems to work fine.
https://codesandbox.io/s/github/tanstack/table/tree/main/examples/react/filters?from-embed=&file=/src/main.tsx
oldo commentedon Sep 13, 2022
I took a page from @LautaroRiveiro suggestion by overriding the
globalFilterFn, but instead of casting all values as aStringI do a check on whether the field is a number, and if so only then make a conversion to a string:alisonatwork commentedon Nov 1, 2022
I think the reason why this is happening is because of the following commit: a5578ac
The default behavior of
getColumnCanGlobalFilterwill now return true for any columns that are either string or number, but the default filter functions don't have the same flexibility. So the various options for working around the bug are as follows:getColumnCanGlobalFilterin your table options so that it goes back to old behavior of only returning true for string type columnsI also hit this problem from a different direction - I wanted to filter on string array type columns - which is possible to do if you have a flexible filter function that handles array types - but that column would never appear because
getColumnCanGlobalFilterfiltered it out.I think there are three things that could happen going forward, assuming the goal is that global filters should be type-flexible in the default case.
getColumnCanGlobalFilterfunction based on supported types (i.e. we should be able to specify which types we want to allow for a particular table without having to override the entire function supplied in default filter options)includesStringwhich can at least handle all of the types allowed bygetColumnCanGlobalFilter, or even better handle any type thrown at it by stringifying itgetColumnCanGlobalFilteris not supplied, all columns are assumed to be globally filterable (https://tanstack.com/table/v8/docs/api/features/filters#can-filter). But that doesn't appear to be the case, because the default options do filter out certain columns (https://github.com/TanStack/table/blob/main/packages/table-core/src/features/Filters.ts#L174). So perhaps the documentation should be updated too.I also noticed if you don't supply a
globalFilterFnit defaults to"auto", which I guess is supposed to figure out the correct filter to use depending on the column type and avoid the user having to do any of this complicated setup themselves, but in my case that's not working either, because it decides to useincludesStringfor a number column.talatkuyuk commentedon Nov 6, 2022
The same issue. I use the latest version
"@tanstack/react-table": "^8.5.22";I am getting
TypeError: o.toLowerCase is not a functionwhen I use the globalFilter feature which is basic one and is not fuzzy implementation.There are one number-type data column, two string-type data columns and a number of display columns in my Table definition. (There is no group header)
If I remove the sole number-type data column, the table does not render at all having the same error.
If I keep the number-type data column, I receive the error when I type the input field which is debounced input related with globalFilter as it is in the examples in the tanstack web site.
OmerWow commentedon Nov 14, 2022
I get the same "o.toLowerCase is not a function" error when I have a number-type column, even on latest v8.5.27 released today.
I solved it by simply adding .toString() on the number column's accessorFn.
While the solution is quite simple, it was not easy to understand and I hope it'll be fixed soon, or at least have better error handling so developers will have a better idea of what to do in this situation.
codebycarlos commentedon Dec 8, 2022
Experiencing the same issue. Solved it thanks to @oldo's suggestion.
stupeyca commentedon Feb 24, 2023
@oldo's solution did the trick for me. But, I was just wondering if there's an actual difference when validating the type of value this way:
The thing is that the conditional in the solution gives:
ssarahs-lab commentedon Mar 2, 2023
works fine when I used "includesString"?
soymartinez commentedon Jun 26, 2023
When you define your columns and you are going to filter specific data from a column make sure to add the
filterFnproperty:hadnazzar commentedon Aug 1, 2023
Thats worked for me! Thanks
elijahkimani commentedon Oct 14, 2023
Alternative way to think about it
I was working with date and numeric columns
The
accessorFnused would return number or dates or undefined depending on the column. This would then make the native sorting functionality to workThe column's
cellfunction would then format the numbers or dates for renderingI noticed that the
globalFilterFnwas ignoring these specific fields when I debugged my codeTo solve this, I had to
accessorFnsortingFnfor the respective columns and access the raw value from Row dataBelow is an example of one column definition
eikowagenknecht commentedon Feb 15, 2024
Shouldn't this be the other way round? At least for me, to filter a
numbercolumn the following works: