--- order: 22 title: en-US: Editable Cells zh-CN: 可编辑单元格 --- ## zh-CN 带单元格编辑功能的表格。 ## en-US Table with editable cells. ````jsx import { Table, Input, Button, Popconfirm, Form } from 'antd'; const FormItem = Form.Item; const EditableContext = React.createContext(); const EditableRow = ({ form, index, ...props }) => ( ); const EditableFormRow = Form.create()(EditableRow); class EditableCell extends React.Component { state = { editing: false, } componentDidMount() { if (this.props.editable) { document.addEventListener('click', this.handleClickOutside, true); } } componentWillUnmount() { if (this.props.editable) { document.removeEventListener('click', this.handleClickOutside, true); } } toggleEdit = () => { const editing = !this.state.editing; this.setState({ editing }, () => { if (editing) { this.input.focus(); } }); } handleClickOutside = (e) => { const { editing } = this.state; if (editing && this.cell !== e.target && !this.cell.contains(e.target)) { this.save(); } } save = () => { const { record, handleSave } = this.props; this.form.validateFields((error, values) => { if (error) { return; } this.toggleEdit(); handleSave({ ...record, ...values }); }); } render() { const { editing } = this.state; const { editable, dataIndex, title, record, index, handleSave, ...restProps } = this.props; return ( (this.cell = node)} {...restProps}> {editable ? ( {(form) => { this.form = form; return ( editing ? ( {form.getFieldDecorator(dataIndex, { rules: [{ required: true, message: `${title} is required.`, }], initialValue: record[dataIndex], })( (this.input = node)} onPressEnter={this.save} /> )} ) : (
{restProps.children}
) ); }}
) : restProps.children} ); } } class EditableTable extends React.Component { constructor(props) { super(props); this.columns = [{ title: 'name', dataIndex: 'name', width: '30%', editable: true, }, { title: 'age', dataIndex: 'age', }, { title: 'address', dataIndex: 'address', }, { title: 'operation', dataIndex: 'operation', render: (text, record) => { return ( this.state.dataSource.length >= 1 ? ( this.handleDelete(record.key)}> Delete ) : null ); }, }]; this.state = { dataSource: [{ key: '0', name: 'Edward King 0', age: '32', address: 'London, Park Lane no. 0', }, { key: '1', name: 'Edward King 1', age: '32', address: 'London, Park Lane no. 1', }], count: 2, }; } handleDelete = (key) => { const dataSource = [...this.state.dataSource]; this.setState({ dataSource: dataSource.filter(item => item.key !== key) }); } handleAdd = () => { const { count, dataSource } = this.state; const newData = { key: count, name: `Edward King ${count}`, age: 32, address: `London, Park Lane no. ${count}`, }; this.setState({ dataSource: [...dataSource, newData], count: count + 1, }); } handleSave = (row) => { const newData = [...this.state.dataSource]; const index = newData.findIndex(item => row.key === item.key); const item = newData[index]; newData.splice(index, 1, { ...item, ...row, }); this.setState({ dataSource: newData }); } render() { const { dataSource } = this.state; const components = { body: { row: EditableFormRow, cell: EditableCell, }, }; const columns = this.columns.map((col) => { if (!col.editable) { return col; } return { ...col, onCell: record => ({ record, editable: col.editable, dataIndex: col.dataIndex, title: col.title, handleSave: this.handleSave, }), }; }); return (
'editable-row'} bordered dataSource={dataSource} columns={columns} /> ); } } ReactDOM.render(, mountNode); ```` ````css .editable-cell { position: relative; } .editable-cell-value-wrap { padding: 5px 12px; cursor: pointer; } .editable-row:hover .editable-cell-value-wrap { border: 1px solid #d9d9d9; border-radius: 4px; padding: 4px 11px; } ````