如何获取material-react-table中已应用的筛选器并在PDF中展示
问题描述
使用material-react-table创建了支持行选择与PDF导出的表格,希望在数据被筛选(例如数量大于5000)时,获取当前应用的筛选器信息(包含筛选列名称与筛选值)并展示在导出的PDF中,提升数据上下文可读性。目前已通过columnFilters状态和onColumnFiltersChange方法获取筛选值,但无法获取对应的筛选列名称。
解决方案
columnFilters数组中的每个筛选对象都包含id字段,该字段对应你定义的列的id。你可以通过这个id在columns配置中找到对应的列标题,然后将筛选条件渲染到PDF中。
具体步骤:
- 编写辅助函数,将
columnFilters转换为包含列标题和筛选值的数组 - 在PDF导出函数中,先渲染筛选条件文本,再渲染数据表格
修改后的完整代码
import React, { useEffect, useState } from "react"; import { Delete } from "@mui/icons-material"; import FileDownloadIcon from '@mui/icons-material/FileDownload'; import { Box, Button, ListItemIcon, MenuItem, lighten } from "@mui/material"; import { jsPDF } from 'jspdf'; import autoTable from 'jspdf-autotable'; import { MRT_GlobalFilterTextField, MRT_ToggleFiltersButton, MaterialReactTable, useMaterialReactTable, } from "material-react-table"; import { MRT_Localization_ES } from "material-react-table/locales/es"; const MovementsTable = ({ movements, commodities, handleOpenDeleteModal }) => { const [columnFilters, setColumnFilters] = useState([]); const columns = [ { id: "created_at", header: "Fecha", columns: [ { accessorFn: (row) => new Date(row.created_at).toLocaleDateString("es-ES", { year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit", }), id: "created_at", header: "Fecha", size: 250, }, ], }, { id: "movement_id", header: "Movimiento Nº", columns: [ { accessorFn: (row) => `${row.movement_id}`, id: "movement_id", header: "Movimiento Nº", size: 250, }, ], }, { id: "form_number", header: "Formulario Nº", columns: [ { accessorFn: (row) => `${row.form_number}`, id: "form_number", header: "Formulario Nº", size: 250, }, ], }, { id: "commodity", header: "Producto", columns: [ { accessorFn: (row) => `${commodities[row.commodity] || "Producto Desconocido"}`, id: "commodity", header: "Producto", size: 250, }, ], }, { id: "quantity", header: "Cantidad [kg]", columns: [ { accessorFn: (row) => `${row.quantity}`, id: "quantity", header: "Cantidad [kg]", size: 250, }, ], }, { id: "origin_destination", header: "Origen/Destino", columns: [ { accessorFn: (row) => `${row.movement_type === "input" ? "Ingreso desde " + row.origin : "Salida hacia " + row.destination}`, id: "origin_destination", header: "Origen/Destino", size: 250, }, ], }, { id: "observations", header: "Observaciones", columns: [ { accessorFn: (row) => `${row.observations}`, id: "observations", header: "Observaciones", size: 250, }, ], }, ]; // 辅助函数:将columnFilters转换为带列标题的筛选条件 const getFilterConditions = () => { return columnFilters.map(filter => { // 找到对应列的标题 const column = columns.find(col => col.id === filter.id); const columnHeader = column?.columns[0].header || filter.id; // 根据筛选类型格式化值(处理范围筛选) let filterValue = filter.value; if (typeof filterValue === 'object') { filterValue = Object.entries(filterValue) .map(([key, val]) => `${key === 'gte' ? '≥' : '≤'} ${val}`) .join(' '); } return { column: columnHeader, value: filterValue }; }); }; const handleExportRows = (rows) => { const doc = new jsPDF('landscape'); const filterConditions = getFilterConditions(); let tableStartY = 20; // 添加筛选条件到PDF顶部 if (filterConditions.length > 0) { doc.setFontSize(14); doc.text('Filtrado aplicado:', 20, tableStartY); tableStartY += 15; doc.setFontSize(12); filterConditions.forEach((condition, index) => { doc.text(`${condition.column}: ${condition.value}`, 30, tableStartY + index * 15); }); tableStartY += filterConditions.length * 15 + 10; } // 处理表格数据 const tableData = rows.map((row) => { return columns.map((column) => { return column.columns[0].accessorFn(row.original) || ''; }) }); const tableHeaders = columns.map((column) => { return column.columns[0].header; }); // 渲染数据表格 autoTable(doc, { startY: tableStartY, head: [tableHeaders], body: tableData, theme: 'grid', headStyles: { fillColor: [2, 129, 67], textColor: [255], }, }); // 保存PDF const now = new Date().toLocaleDateString('es-ES', { year: 'numeric', month: '2-digit', day: '2-digit', }).replace(/\//g, '-'); doc.save(`oilcan-movements-report-${now}.pdf`); }; useEffect(() => { console.log(columnFilters); }, [columnFilters]); const table = useMaterialReactTable({ columns, data: movements, enableColumnFilterModes: true, enableColumnOrdering: true, enableGrouping: true, enableColumnPinning: true, enableFacetedValues: true, enableRowActions: true, onColumnFiltersChange: setColumnFilters, state: { columnFilters }, enableRowSelection: true, localization: MRT_Localization_ES, initialState: { showColumnFilters: true, showGlobalFilter: true, columnPinning: { right: ["mrt-row-actions"], }, }, paginationDisplayMode: "pages", positionToolbarAlertBanner: "bottom", muiTableBodyRowProps: ({ row }) => ({ sx: { backgroundColor: row.original.movement_type === "input" ? "#00800075" : "#ff000078", }, }), muiSearchTextFieldProps: { size: "small", variant: "outlined", }, muiPaginationProps: { color: "secondary", rowsPerPageOptions: [10, 20, 30], shape: "rounded", variant: "outlined", }, renderRowActionMenuItems: ({ row, closeMenu }) => [ <MenuItem key={0} onClick={() => { handleOpenDeleteModal(row.original.movement_id); closeMenu(); }} sx={{ m: 0 }} > <ListItemIcon> <Delete /> </ListItemIcon> Eliminar Movimiento </MenuItem>, ], renderTopToolbar: ({ table }) => { return ( <Box sx={(theme) => ({ backgroundColor: lighten(theme.palette.background.default, 0.05), display: "flex", gap: "0.5rem", p: "8px", justifyContent: "space-between", })} > <Box sx={{ display: "flex", gap: "0.5rem", alignItems: "center" }}> <MRT_GlobalFilterTextField table={table} /> <MRT_ToggleFiltersButton table={table} /> </Box> <Button disabled={ !table.getIsSomeRowsSelected() && !table.getIsAllRowsSelected() } onClick={() => handleExportRows(table.getSelectedRowModel().rows)} startIcon={<FileDownloadIcon />} > Exportar Filas Seleccionadas </Button> </Box> ); }, renderTopToolbarCustomActions: ({ table }) => ( <Box sx={{ display: 'flex', gap: '16px', padding: '8px', flexWrap: 'wrap', }} > <Button disabled={table.getPrePaginationRowModel().rows.length === 0} onClick={() => handleExportRows(table.getPrePaginationRowModel().rows) } startIcon={<FileDownloadIcon />} > Export All Rows </Button> <Button disabled={table.getRowModel().rows.length === 0} onClick={() => handleExportRows(table.getRowModel().rows)} startIcon={<FileDownloadIcon />} > Export Page Rows </Button> <Button disabled={ !table.getIsSomeRowsSelected() && !table.getIsAllRowsSelected() } onClick={() => handleExportRows(table.getSelectedRowModel().rows)} startIcon={<FileDownloadIcon />} > Export Selected Rows </Button> </Box> ), }); return <MaterialReactTable table={table} />; }; export default MovementsTable;
关键修改说明
- 添加
getFilterConditions辅助函数:通过筛选对象的id匹配列配置中的标题,同时格式化范围筛选的显示文本 - 调整
handleExportRows函数:动态在PDF顶部添加筛选条件,根据筛选数量调整数据表格的起始位置,避免内容重叠 - 保留原有导出逻辑,确保数据表格的样式和功能不受影响
内容的提问来源于stack exchange,提问作者Alejo Nuñez
相关产品推荐
相关产品推荐

