How to implement server-side columns filtering with different filter operators in TanStack Table (React-Table V8)

2.1k views Asked by At

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 .

0

There are 0 answers