Guía de filtrado de columnas
Ejemplos
¿Quieres saltar a la implementación? Echa un vistazo a estos ejemplos:
- filtros (incluye facetado)
- datos-editables
- expansión
- agrupación
- paginación
- selección-de-filas
API
Guía de filtrado de columnas
El filtrado se presenta en 2 modalidades: Filtrado por columna y Filtrado global.
Esta guía se centrará en el filtrado por columna, que es un filtro que se aplica al valor del "accessor" de una sola columna.
TanStack Table soporta tanto el filtrado del lado del cliente como el filtrado manual del lado del servidor. Esta guía explicará cómo implementar y personalizar ambos, y te ayudará a decidir cuál es el mejor para tu caso de uso.
Filtrado del lado del cliente vs. del lado del servidor
Si tienes un conjunto de datos grande, es posible que no quieras cargar todos esos datos en el navegador del cliente para filtrarlos. En este caso, lo más probable es que quieras implementar filtrado, ordenación, paginación, etc., del lado del servidor.
Sin embargo, como también se discute en la Guía de Paginación, muchos desarrolladores subestiman cuántas filas se pueden cargar del lado del cliente sin una penalización en el rendimiento. Los ejemplos de TanStack Table a menudo se prueban para manejar hasta 100,000 filas o más con un rendimiento decente para filtrado, ordenación, paginación y agrupación del lado del cliente. Esto no significa necesariamente que tu aplicación podrá manejar tantas filas, pero si tu tabla solo va a tener unos pocos miles de filas como máximo, podrías aprovechar el filtrado, ordenación, paginación y agrupación del lado del cliente que ofrece TanStack Table.
TanStack Table puede manejar miles de filas del lado del cliente con buen rendimiento. No descartes el filtrado, paginación, ordenación, etc., del lado del cliente sin antes pensarlo un poco.
Cada caso de uso es diferente y dependerá de la complejidad de la tabla, cuántas columnas tengas, cuán grande sea cada pieza de datos, etc. Los principales cuellos de botella a los que prestar atención son:
- ¿Puede tu servidor consultar todos los datos en un tiempo (y costo) razonable?
- ¿Cuál es el tamaño total de la solicitud? (Esto podría no escalar tan mal como piensas si no tienes muchas columnas).
- ¿Está utilizando el navegador del cliente demasiada memoria si todos los datos se cargan a la vez?
Si no estás seguro, siempre puedes empezar con el filtrado y paginación del lado del cliente y luego cambiar a estrategias del lado del servidor en el futuro a medida que tus datos crezcan.
Filtrado manual del lado del servidor
Si has decidido que necesitas implementar el filtrado del lado del servidor en lugar de usar el filtrado del lado del cliente integrado, así es como lo haces.
No se necesita la opción de tabla getFilteredRowModel para el filtrado manual del lado del servidor. En su lugar, los data que pasas a la tabla ya deben estar filtrados. Sin embargo, si has pasado una opción de tabla getFilteredRowModel, puedes indicarle a la tabla que la omita configurando la opción manualFiltering en true.
const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
// getFilteredRowModel: getFilteredRowModel(), // no es necesario para el filtrado manual del lado del servidor
manualFiltering: true,
});
Nota: Al usar el filtrado manual, muchas de las opciones que se discuten en el resto de esta guía no tendrán ningún efecto. Cuando
manualFilteringse establece entrue, la instancia de la tabla no aplicará ninguna lógica de filtrado a las filas que se le pasen. En su lugar, asumirá que las filas ya están filtradas y usará losdataque se le pasen tal cual.
Filtrado del lado del cliente
Si estás utilizando las características de filtrado del lado del cliente integradas, primero debes pasar una función getFilteredRowModel a las opciones de la tabla. Esta función se llamará cada vez que la tabla necesite filtrar los datos. Puedes importar la función getFilteredRowModel predeterminada de TanStack Table o crear la tuya propia.
import { useReactTable, getFilteredRowModel } from "@tanstack/react-table";
//...
const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
getFilteredRowModel: getFilteredRowModel(), // necesario para el filtrado del lado del cliente
});
Estado del filtro de columna
Independientemente de si utilizas filtrado del lado del cliente o del lado del servidor, puedes aprovechar la gestión del estado de filtrado de columnas integrada que proporciona TanStack Table. Hay muchas APIs de tabla y columna para mutar e interactuar con el estado del filtro y recuperar el estado del filtro de columna.
El estado de filtrado de columnas se define como un array de objetos con la siguiente forma:
interface ColumnFilter {
id: string;
value: unknown;
}
type ColumnFiltersState = ColumnFilter[];
Dado que el estado del filtro de columna es un array de objetos, puedes tener múltiples filtros de columna aplicados a la vez.
Accediendo al estado del filtro de columna
Puedes acceder al estado del filtro de columna desde la instancia de la tabla como cualquier otro estado de la tabla usando la API table.getState().
const table = useReactTable({
columns,
data,
//...
});
console.log(table.getState().columnFilters); // accede al estado de los filtros de columna desde la instancia de la tabla
Sin embargo, si necesitas acceder al estado del filtro de columna antes de que la tabla se inicialice, puedes "controlar" el estado del filtro de columna como se muestra a continuación.
Estado controlado del filtro de columna
Si necesitas un fácil acceso al estado del filtro de columna, puedes controlar/gestionar el estado del filtro de columna en tu propia gestión de estado con las opciones de tabla state.columnFilters y onColumnFiltersChange.
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]); // se puede establecer el estado inicial del filtro de columna aquí
//...
const table = useReactTable({
columns,
data,
//...
state: {
columnFilters,
},
onColumnFiltersChange: setColumnFilters,
});
Estado inicial del filtro de columna
Si no necesitas controlar el estado del filtro de columna en tu propia gestión o ámbito de estado, pero aún deseas establecer un estado de filtro de columna inicial, puedes usar la opción de tabla initialState en lugar de state.
const table = useReactTable({
columns,
data,
//...
initialState: {
columnFilters: [
{
id: "name",
value: "John", // filtra la columna 'name' por 'John' por defecto
},
],
},
});
NOTA: No uses
initialState.columnFiltersystate.columnFiltersal mismo tiempo, ya que el estado inicializado enstate.columnFiltersanularáinitialState.columnFilters.
FilterFns
Cada columna puede tener su propia lógica de filtrado única. Elige entre cualquiera de las funciones de filtro proporcionadas por TanStack Table, o crea la tuya propia.
Por defecto, hay 10 funciones de filtro integradas para elegir:
includesString- Inclusión de cadena sin distinción entre mayúsculas y minúsculasincludesStringSensitive- Inclusión de cadena con distinción entre mayúsculas y minúsculasequalsString- Igualdad de cadena sin distinción entre mayúsculas y minúsculasequalsStringSensitive- Igualdad de cadena con distinción entre mayúsculas y minúsculasarrIncludes- Inclusión de elemento dentro de un arrayarrIncludesAll- Todos los elementos incluidos en un arrayarrIncludesSome- Algunos elementos incluidos en un arrayequals- Igualdad de objeto/referencialObject.is/===weakEquals- Igualdad de objeto/referencial débil==inNumberRange- Inclusión de rango numérico
También puedes definir tus propias funciones de filtro personalizadas, ya sea como la opción de columna filterFn o como una función de filtro global usando la opción de tabla filterFns.
Funciones de filtro personalizadas
Nota: Estas funciones de filtro solo se ejecutan durante el filtrado del lado del cliente.
Al definir una función de filtro personalizada, ya sea en la opción de columna filterFn o en la opción de tabla filterFns, debe tener la siguiente firma:
const myCustomFilterFn: FilterFn = (
row: Row,
columnId: string,
filterValue: any,
addMeta: (meta: any) => void,
) => boolean;
Cada función de filtro recibe:
- La fila a filtrar
- El
columnIda usar para recuperar el valor de la fila - El valor del filtro
y debe retornar true si la fila debe incluirse en las filas filtradas, y false si debe ser eliminada.
const columns = [
{
header: () => "Nombre",
accessorKey: "name",
filterFn: "includesString", // usar función de filtro integrada
},
{
header: () => "Edad",
accessorKey: "age",
filterFn: "inNumberRange",
},
{
header: () => "Cumpleaños",
accessorKey: "birthday",
filterFn: "myCustomFilterFn", // usar función de filtro global personalizada
},
{
header: () => "Perfil",
accessorKey: "profile",
// usar función de filtro personalizada directamente
filterFn: (row, columnId, filterValue) => {
return; // true o false basado en tu lógica personalizada
},
},
];
//...
const table = useReactTable({
columns,
data,
getCoreRowModel: getCoreRowModel(),
getFilteredRowModel: getFilteredRowModel(),
filterFns: {
//añadir una función de ordenación personalizada
myCustomFilterFn: (row, columnId, filterValue) => {
//definida aquí en línea
return; // true o false basado en tu lógica personalizada
},
startsWith: startsWithFilterFn, // definida en otro lugar
},
});
Personalizar el comportamiento de la función de filtro
Puedes adjuntar algunas otras propiedades a las funciones de filtro para personalizar su comportamiento:
-
filterFn.resolveFilterValue- Este método "colgante" opcional en cualquierfilterFnpermite a la función de filtro transformar/sanear/formatear el valor del filtro antes de que se pase a la función de filtro. -
filterFn.autoRemove- A este método "colgante" opcional en cualquierfilterFnse le pasa un valor de filtro y se espera que devuelvatruesi el valor del filtro debe eliminarse del estado del filtro. Por ejemplo, algunos filtros de tipo booleano pueden querer eliminar el valor del filtro del estado de la tabla si el valor del filtro se establece enfalse.
const startsWithFilterFn = <TData extends MRT_RowData>(
row: Row<TData>,
columnId: string,
filterValue: number | string, // resolveFilterValue transformará esto a una cadena
) =>
row
.getValue<number | string>(columnId)
.toString()
.toLowerCase()
.trim()
.startsWith(filterValue); // toString, toLowerCase, y trim el valor del filtro en `resolveFilterValue`
// eliminar el valor del filtro del estado del filtro si es falsy (cadena vacía en este caso)
startsWithFilterFn.autoRemove = (val: any) => !val;
// transformar/sanear/formatear el valor del filtro antes de que se pase a la función de filtro
startsWithFilterFn.resolveFilterValue = (val: any) =>
val.toString().toLowerCase().trim();
Personalizar el filtrado de columnas
Existen muchas opciones de tabla y columna que puedes usar para personalizar aún más el comportamiento del filtrado de columnas.
Desactivar el filtrado de columnas
Por defecto, el filtrado de columnas está habilitado para todas las columnas. Puedes desactivar el filtrado de columnas para todas las columnas o para columnas específicas usando la opción de tabla enableColumnFilters o la opción de columna enableColumnFilter. También puedes desactivar tanto el filtrado de columnas como el global estableciendo la opción de tabla enableFilters en false.
Desactivar el filtrado de columnas para una columna hará que la API column.getCanFilter devuelva false para esa columna.
const columns = [
{
header: () => "Id",
accessorKey: "id",
enableColumnFilter: false, // deshabilitar el filtrado de columnas para esta columna
},
//...
];
//...
const table = useReactTable({
columns,
data,
enableColumnFilters: false, // deshabilitar el filtrado de columnas para todas las columnas
});
Filtrado de sub-filas (Expansión)
Existen algunas opciones de tabla adicionales para personalizar el comportamiento del filtrado de columnas al usar características como expansión, agrupación y agregación.
Filtrar desde filas hoja
Por defecto, el filtrado se realiza desde las filas padre hacia abajo, de modo que si una fila padre es filtrada, todas sus sub-filas hijas también lo serán. Dependiendo de tu caso de uso, este puede ser el comportamiento deseado si solo quieres que el usuario busque entre las filas de nivel superior, y no entre las sub-filas. Esta es también la opción más eficiente.
Sin embargo, si quieres permitir que las sub-filas sean filtradas y buscadas, independientemente de si la fila padre es filtrada, puedes establecer la opción de tabla filterFromLeafRows en true. Establecer esta opción en true hará que el filtrado se realice desde las filas hoja hacia arriba, lo que significa que las filas padre se incluirán siempre que una de sus filas hijas o nietas también esté incluida.
const table = useReactTable({
columns,
data,
getCoreRowModel: getCoreRowModel(),
getFilteredRowModel: getFilteredRowModel(),
getExpandedRowModel: getExpandedRowModel(),
filterFromLeafRows: true, // filtrar y buscar a través de sub-filas
});
Profundidad máxima del filtro de filas hoja
Por defecto, el filtrado se realiza para todas las filas en un árbol, sin importar si son filas padre de nivel raíz o filas hoja hijas de una fila padre. Establecer la opción de tabla maxLeafRowFilterDepth en 0 hará que el filtrado solo se aplique a las filas padre de nivel raíz, quedando todas las sub-filas sin filtrar. De manera similar, establecer esta opción en 1 hará que el filtrado solo se aplique a las filas hoja hijas de 1 nivel de profundidad, y así sucesivamente.
Usa maxLeafRowFilterDepth: 0 si quieres preservar las sub-filas de una fila padre para que no sean filtradas mientras la fila padre pasa el filtro.
const table = useReactTable({
columns,
data,
getCoreRowModel: getCoreRowModel(),
getFilteredRowModel: getFilteredRowModel(),
getExpandedRowModel: getExpandedRowModel(),
maxLeafRowFilterDepth: 0, // solo filtra las filas padre de nivel raíz
});
APIs de filtrado de columnas
Existen muchas APIs de Columna y Tabla que puedes usar para interactuar con el estado del filtro de columna y conectarlas a tus componentes de UI. Aquí hay una lista de las APIs disponibles y sus casos de uso más comunes:
-
table.setColumnFilters- Sobrescribe todo el estado del filtro de columna con un nuevo estado -
table.resetColumnFilters- Útil para un botón de "borrar todo/restablecer filtros" -
column.getFilterValue- Útil para obtener el valor de filtro inicial predeterminado para una entrada, o incluso para proporcionar directamente el valor del filtro a una entrada de filtro -
column.setFilterValue- Útil para conectar las entradas de filtro a sus controladoresonChangeoonBlur -
column.getCanFilter- Útil para deshabilitar/habilitar las entradas de filtro -
column.getIsFiltered- Útil para mostrar un indicador visual de que una columna está siendo filtrada actualmente -
column.getFilterIndex- Útil para mostrar en qué orden se está aplicando el filtro actual -
column.getAutoFilterFn- -
column.getFilterFn- Útil para mostrar qué modo o función de filtro se está utilizando actualmente