如何实现Antd树形表格(Tree Table)的可编辑功能?
Antd树形表格(Tree Table)可编辑实现方案
你的问题核心在于Antd树形表格的行组件并非普通表格的body.row,而是treeRow,原代码中components配置错误,导致EditableRow没有被正确挂载,EditableCell无法获取到上下文里的Form实例,因此点击单元格无法触发编辑状态。此外,原代码缺少树形数据的更新逻辑,即使编辑成功也无法保存修改。
关键修改点
- 修正组件配置:将树形表格的行组件指定为
treeRow,而非普通表格的body.row - 实现树形数据递归更新:树形结构的数据需要递归查找目标节点并更新
- 传递保存回调:确保
handleSave函数能传递到EditableCell中
修改后的完整代码
import React from 'react'; import './index.css'; import { Button, Form, Input, Popconfirm, Table, Space, Switch } from 'antd'; import { useContext, useEffect, useRef, useState } from 'react'; const columns = [ { title: 'Name', dataIndex: 'name', key: 'name', editable: true }, { title: 'Age', dataIndex: 'age', key: 'age', width: '12%', editable: true, }, { title: 'Address', dataIndex: 'address', width: '30%', key: 'address', }, ]; const data = [ { key: 1, name: 'John Brown sr.', age: 60, address: 'New York No. 1 Lake Park', children: [ { key: 11, name: 'John Brown', age: 42, address: 'New York No. 2 Lake Park', }, { key: 12, name: 'John Brown jr.', age: 30, address: 'New York No. 3 Lake Park', children: [ { key: 121, name: 'Jimmy Brown', age: 16, address: 'New York No. 3 Lake Park', }, ], }, { key: 13, name: 'Jim Green sr.', age: 72, address: 'London No. 1 Lake Park', children: [ { key: 131, name: 'Jim Green', age: 42, address: 'London No. 2 Lake Park', children: [ { key: 1311, name: 'Jim Green jr.', age: 25, address: 'London No. 3 Lake Park', }, { key: 1312, name: 'Jimmy Green sr.', age: 18, address: 'London No. 4 Lake Park', }, ], }, ], }, ], }, { key: 2, name: 'Joe Black', age: 32, address: 'Sydney No. 1 Lake Park', }, ]; const EditableContext = React.createContext(null); const EditableRow = ({ index, ...props }) => { const [form] = Form.useForm(); return ( <Form form={form} component={false}> <EditableContext.Provider value={form}> <tr {...props} /> </EditableContext.Provider> </Form> ); }; const EditableCell = ({ title, editable, children, dataIndex, record, handleSave, ...restProps }) => { const [editing, setEditing] = useState(false); const inputRef = useRef(null); const form = useContext(EditableContext); useEffect(() => { if (editing) { inputRef.current?.focus(); } }, [editing]); const toggleEdit = () => { setEditing(!editing); form.setFieldsValue({ [dataIndex]: record[dataIndex], }); }; const save = async () => { try { const values = await form.validateFields(); toggleEdit(); handleSave({ ...record, ...values, }); } catch (errInfo) { console.log('Save failed:', errInfo); } }; let childNode = children; if (editable) { childNode = editing ? ( <Form.Item style={{ margin: 0 }} name={dataIndex} rules={[{ required: true, message: `${title} is required.` }]} > <Input ref={inputRef} onPressEnter={save} onBlur={save} /> </Form.Item> ) : ( <div className="editable-cell-value-wrap" style={{ paddingRight: 24 }} onClick={toggleEdit} > {children} </div> ); } return <td {...restProps}>{childNode}</td>; }; const App = () => { const [treeData, setTreeData] = useState(data); // 递归更新树形数据中的指定节点 const updateTreeData = (list, key, updatedObj) => { return list.map(item => { if (item.key === key) { return { ...item, ...updatedObj }; } if (item.children) { return { ...item, children: updateTreeData(item.children, key, updatedObj) }; } return item; }); }; const handleSave = (updatedRecord) => { setTreeData(prev => updateTreeData(prev, updatedRecord.key, updatedRecord)); }; // 为可编辑列配置onCell,传递必要参数 const editableColumns = columns.map(col => { if (!col.editable) return col; return { ...col, onCell: (record) => ({ record, editable: col.editable, dataIndex: col.dataIndex, title: col.title, handleSave, }), }; }); const components = { body: { cell: EditableCell, }, treeRow: EditableRow, // 树形表格使用treeRow作为行组件 }; return ( <> <Table columns={editableColumns} components={components} dataSource={treeData} pagination={false} treeDefaultExpandAll // 默认展开所有树形节点,方便测试 /> </> ); }; export default App;
说明
- 组件配置修正:
components中指定treeRow: EditableRow,这是树形表格行组件的正确配置项,普通表格用body.row,树形表格必须用treeRow - 树形数据更新:
updateTreeData函数通过递归遍历树形结构,找到对应key的节点并更新,确保修改能正确反映到数据源中 - 参数传递:通过
onCell将handleSave等必要参数传递给EditableCell,保证编辑完成后能触发保存逻辑
内容的提问来源于stack exchange,提问作者Deep Kumar Singh
相关产品推荐
相关产品推荐

