reactjs - Hur man implementerar server-side kolumnfiltrering med olika filteroperatörer i TanStack Table (React-Table V8)


Jag försöker implementera server-sidig kolumnfiltrering i TanStack Table (React-Table V8). Problemet är att jag inte vet hur man konverterar ColumnFiltersState-objektet till rätt format för backend. Min backend använder nestjs-paginate som använder följande operatorer: $eq, $not, $null, $in, $gt, $gte, $lt, $lte, $btw, $ilike för filtrering baserat på frågan. ColumnFiltersState innehåller ett value-fält, vilket är av typen unknown, och värdet det innehåller kommer att bero på vilken filterkomponent som används. Jag planerar att använda select, datumfält, intervallfält för filtrering. Dessutom kan vissa fält filtreras som 'innehåller', 'är lika med' etc.

Dessutom är ett annat problem att jag behöver stödja både klient- och serverbaserad kolumnfiltrering beroende på manualFiltering-egenskapen som skickas till min anpassade tabellkomponent.

Här är en del kod från min UsersList-komponent som använder min egna tabell:

...
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: ...,
        },
      };
    }),
  });
...

Så då kan jag skicka det till servern i det behövda formatet:

// 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,
        };
      },
...

Här är nestjs-paginate-typerna:

// 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;
  };
}

En möjlig lösning är att lägga till en anpassad prop till ColumnMeta genom vilken det kommer att vara möjligt att avgöra vilken filtreringsoperator som ska användas, men då vet jag inte hur man gör det korrekt eller kanske kan jag avgöra det med de inbyggda lösningarna. Jag skulle uppskatta all hjälp och idéer 🙂.

Relaterade artiklar