I am trying to implement server-side column filtering in TanStack Table (React-Table V8). The problem is that I don't know how to convert the ColumnFiltersState
object to the right format for the backend. My backend uses nestjs-paginate which uses the following operators: $eq, $not, $null, $in, $gt, $gte, $lt, $lte, $btw, $ilike
for filtering based on the query. The ColumnFiltersState
contains a value
field, which is of type unknown
, and the value it contains will depend on the filter component being used, I plan to use select, date inputs, range inputs for filtering. Also, some fields can be filtered as 'contains', 'equals' etc.
Additionally, another problem is that I need to support both client-side and server-side column filtering depending on the manualFiltering
prop passed to my custom table component.
Here is a piece of code from my UsersList component which use my custom table:
...
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
[],
);
const { data, isFetching, isLoading, isSuccess, isError } = useGetUsersQuery({
search: globalFilter,
page: pageIndex + 1,
limit: pageSize,
sortBy: sorting.map((s) => `${s.id}:${s.desc ? 'DESC' : 'ASC'}`).join(','),
columnFilters: columnFilters.map((columnFilter) => { // Here is the problem
...
return {
column: columnFilter.id,
filter: {
operator: ...,
value: ...,
},
};
}),
});
...
So then I can send it to the server in the needed format:
// user.api.ts
...
query: ({ search, page, limit, sortBy, columnFilters }) => {
const params: any = {
page,
limit,
search,
sortBy,
};
// example query URL with filters:
// http://localhost:3000/cats?filter.age=$gte:3
if (columnFilters) {
columnFilters.forEach(({ column, filter: { operator, value } }) => {
params[`filter.${column}`] = `${operator}:${value}`;
});
}
return {
url: 'users/',
params,
};
},
...
Here are the nestjs-paginate
types:
// Available filter operators:
export enum FilterOperator {
EQ = '$eq',
GT = '$gt',
GTE = '$gte',
IN = '$in',
NULL = '$null',
LT = '$lt',
LTE = '$lte',
BTW = '$btw',
NOT = '$not',
ILIKE = '$ilike',
}
// Return data type from the backend
export interface Paginated<T> {
data: T[];
meta: {
itemsPerPage: number;
totalItems: number;
currentPage: number;
totalPages: number;
sortBy: SortBy<T>;
searchBy: Column<T>[];
search: string;
filter?: {
[column: string]: string | string[];
};
};
links: {
first?: string;
previous?: string;
current: string;
next?: string;
last?: string;
};
}
A possible solution is to add a custom prop to ColumnMeta
by which it will be possible to determine which filtering operator to use, but then I don’t know how to do it correctly or maybe I could determine it using the built-in solutions. I would appreciate any help and ideas .