在上一部分中,我们详细介绍了创建具有动态列模式的可编辑 React 表格的方法。我们还利用 TanStack Table 来简化这个过程。
在本文,我们将继续在之前所做的基础上进行构建,并给具有多行选择的表格增加删除和添加行的功能。
下面展示了我们希望在本教程结束时表格的外观和行为:
添加表格行
要启用添加表格行,我们必须添加“添加行”按钮,然后创建逻辑以将空行插入数据数组。
让我们首先添加在主表组件中插入行的逻辑。与之前的方法一样,我们将在useReactTableHook
中的meta
对象中添加。这样,我们就可以通过主table
对象在任何地方访问它:
const table = useReactTable({ data, columns, getCoreRowModel: getCoreRowModel(), meta: { editedRows, setEditedRows, revertData: (...) => { ... }, updateData: (...) => { ... }, addRow: () => { const newRow: Student = { studentId: Math.floor(Math.random() * 10000), name: "", dateOfBirth: "", major: "", }; const setFunc = (old: Student[]) => [...old, newRow]; setData(setFunc); setOriginalData(setFunc); }, }, });
请注意,我们还更新了originalData
数组,因为我们需要使它们保持同步,以实现第一部分中讨论的取消/保存行功能。
现在,我们可以创建一个带有按钮和事件处理程序的页脚单元组件来使用该addRow
函数。
export const FooterCell = ({ table }) => { const meta = table.options.meta return ( <div className="footer-buttons"> <button className="add-button" onClick={meta?.addRow}> Add New + </button> </div> ) }
最后,我们需要将FooterCell
组件显示在表格上的某个位置以供用户使用。有多种选择,但将其添加到页脚的主表可能是一个好地方,因为它会看起来更加集成。
import { FooterCell } from '../Table/FooterCell'; export const Table = () => { const [data, setData] = useState(() => [...defaultData]); const [originalData, setOriginalData] = useState(() => [...defaultData]); const [editedRows, setEditedRows] = useState({}); const table = useReactTable({ data, columns, getCoreRowModel: getCoreRowModel(), meta: { editedRows, setEditedRows, revertData: (...) => { ... }, updateData: (...) => { ... }, addRow: () => { const newRow: Student = { studentId: Math.floor(Math.random() * 10000), name: "", dateOfBirth: "", major: "", }; const setFunc = (old: Student[]) => [...old, newRow]; setData(setFunc); setOriginalData(setFunc); }, }, }); return ( <article className="table-container"> <table> <thead> ... </thead> <tbody> ... </tbody> <tfoot> <tr> <th colSpan={table.getCenterLeafColumns().length} align="right"> <FooterCell table={table} /> </th> </tr> </tfoot> </table> </article> ); };
下面是上面代码的一个实时示例,带有如下按钮样式:
table .footer-buttons button { border: none; background-color: transparent; } table .add-button { color: #4bbd7f; }
删除表格行
删除表格行将遵循与上一节相同的方法。让我们首先添加removeRow
函数,这是一种简单的单行过滤方法,用于从数据和原始数据数组中删除行。
const table = useReactTable({ data, columns, getCoreRowModel: getCoreRowModel(), meta: { editedRows, setEditedRows, revertData: (...) => { ... }, updateData: (...) => { ... }, addRow: () => { ... }, removeRow: (rowIndex: number) => { const setFilterFunc = (old: Student[]) => old.filter((_row: Student, index: number) => index !== rowIndex); setData(setFilterFunc); setOriginalData(setFilterFunc); }, }, });
对于“删除”按钮,不需要创建新组件,因为它将位于EditCell
组件中“编辑”按钮旁边。
现在,我们可以在EditCell
组件中添加一个removeRow
函数,并在“删除”按钮的onClick
事件上调用它。
export const EditCell = ({ row, table }) => { const meta = table.options.meta; const setEditedRows = (...) => { ... }; const removeRow = () => { meta?.removeRow(row.index); }; return ( <div className="edit-cell-container"> {meta?.editedRows[row.id] ? ( <div className="edit-cell-action"> <button onClick={setEditedRows} name="cancel"> ⚊ </button>{" "} <button onClick={setEditedRows} name="done"> ✔ </button> </div> ) : ( <div className="edit-cell-action"> <button onClick={setEditedRows} name="edit"> ✐ </button> <button onClick={removeRow} name="remove"> X </button> </div> )} </div> ); };
请注意,为了更清晰起见,我们将“取消”图标更改为减号 (⚊),将“删除”图标更改为叉号 (X)。
下面是上面代码的现场演示,其中包含一些按钮样式和对齐方式:
table .edit-cell-action button[name="edit"] { color: #ffb918; } table .edit-cell-action button[name="cancel"] { color: #7b7b7b; } table .edit-cell-action button[name="done"] { color: #4bbd7f; } table .edit-cell-action button[name="remove"] { color: red; background-color: rgb(230, 208, 208); } table .edit-cell-action { display: flex; gap: 5px; }
删除表格的多行
一次选择和删除多行总是很有帮助的。幸运的是,TanStack Table 提供开箱即用的行选择功能。我们需要做的就是启用该功能并传入正确的方法;它将为我们管理剩下的事情。
首先,我们将在useReactTable
中添加enableRowSelection
并创建一个新的removeSelectedRows
函数。该函数将接收选定行 ID 的数组,并将其从data
数组中过滤掉。
const table = useReactTable({ data, columns, getCoreRowModel: getCoreRowModel(), enableRowSelection: true, meta: { editedRows, setEditedRows, revertData: (...) => { ... }, updateData: (...) => { ... }, addRow: () => { ... }, removeRow: (...) => { ... }, removeSelectedRows: (selectedRows: number[]) => { const setFilterFunc = (old: Student[]) => old.filter((_row, index) => !selectedRows.includes(index)); setData(setFilterFunc); setOriginalData(setFilterFunc); }, }, });
然后,在EditCell
组件中,我们将添加一个带有适当属性的复选框,以捕获和更新所选行。事件处理程序来自useReactTable
钩子中可供我们使用的row
对象。
export const EditCell = ({ row, table }) => { const meta = table.options.meta; const setEditedRows = (...) => { ... }; const removeRow = () => { meta?.removeRow(row.index); }; return ( <div className="edit-cell-container"> {meta?.editedRows[row.id] ? ( <div className="edit-cell-action"> <button onClick={setEditedRows} name="cancel"> ⚊ </button>{" "} <button onClick={setEditedRows} name="done"> ✔ </button> </div> ) : ( <div className="edit-cell-action"> <button onClick={setEditedRows} name="edit"> ✐ </button> <button onClick={removeRow} name="remove"> X </button> </div> )} <input type="checkbox" checked={row.getIsSelected()} onChange={row.getToggleSelectedHandler()} /> </div> ); };
最后,我们将向FooterCell
组件添加一个新Remove Selected
按钮并从meta
对象传入removeSelectedRows
函数。可以从具有rows
属性的getSelectedRowModel
函数中检索选定的行。
export const FooterCell = ({ table }) => { const meta = table.options.meta const selectedRows = table.getSelectedRowModel().rows const removeRows = () => { meta.removeSelectedRows( table.getSelectedRowModel().rows.map(row => row.index) ) table.resetRowSelection() } return ( <div className="footer-buttons"> {selectedRows.length > 0 ? ( <button className="remove-button" onClick={removeRows}> Remove Selected x </button> ) : null} <button className="add-button" onClick={meta?.addRow}> Add New + </button> </div> ) }
此外,我们添加了一个条件,仅当存在选定行时才显示Remove Selected
按钮。
下面是最终的演示,以及Remove Selected
按钮和复选框的其余样式:
table .edit-cell-container { display: flex; justify-content: end; align-items: center; gap: 4px; } table input[type="checkbox"] { width: 16px; height: 16px; } table .remove-button { color: #e44747; }
完整代码
完整的代码可以在这个仓库中找到。如果您喜欢本教程,请为仓库加星,并随时提出新功能的需求!
总结
在本教程中,我们学习了如何在 React 表格中添加和删除行。我们还学习了如何添加复选框以通过单击选择和删除多行。