ant design 嵌套table表单
嵌套表单的封装

示例图跟下面的代码有不同,代码实现的是类似的逻辑。
封装的table表单TableForm.js
import React, { PureComponent, Fragment } from 'react';
import { Table, Button, Input, message, Popconfirm, Divider, Select } from 'antd';
import isEqual from 'lodash/isEqual';
const { Option } = Select;
class TableForm extends PureComponent {
index = 0;
cacheOriginData = {};
constructor(props) {
super(props);
this.state = {
data: props.value,
loading: false,
value: props.value,
};
}
static getDerivedStateFromProps(nextProps, preState) {
if (isEqual(nextProps.value, preState.value)) {
return null;
}
return {
data: nextProps.value,
value: nextProps.value,
};
}
getRowByKey(key, newData) {
const { data } = this.state;
return (newData || data).filter(item => item.key === key)[0];
}
toggleEditable = (e, key) => {
e.preventDefault();
const { data } = this.state;
const newData = data.map(item => ({ ...item }));
const target = this.getRowByKey(key, newData);
if (target) {
// 进入编辑状态时保存原始数据
if (!target.editable) {
this.cacheOriginData[key] = { ...target };
}
target.editable = !target.editable;
this.setState({ data: newData });
}
};
newMember = () => {
const { data } = this.state;
const newData = data.map(item => ({ ...item }));
newData.push({
key: `ID_${new Date().getTime()}`,
name: '',
sub_name: '',
reg: '',
editable: true,
isNew: true,
});
this.index += 1;
this.setState({ data: newData });
};
remove(key) {
const { data } = this.state;
const { onChange } = this.props;
const newData = data.filter(item => item.key !== key);
this.setState({ data: newData });
onChange(newData);
}
handleKeyPress(e, key) {
if (e.key === 'Enter') {
this.saveRow(e, key);
}
}
handleFieldChange(e, fieldName, key) {
const { data } = this.state;
const newData = data.map(item => ({ ...item }));
const target = this.getRowByKey(key, newData);
if (target) {
target[fieldName] = e.target?e.target.value:e;
this.setState({ data: newData });
}
}
saveRow(e, key) {
e.persist();
this.setState({
loading: true,
});
setTimeout(() => {
if (this.clickedCancel) {
this.clickedCancel = false;
return;
}
const target = this.getRowByKey(key) || {};
if (!target.sub_name || !target.name || !target.reg) {
message.error('请填写完整信息。');
e.target.focus();
this.setState({
loading: false,
});
return;
}
delete target.isNew;
this.toggleEditable(e, key);
const { data } = this.state;
const { onChange } = this.props;
onChange(data);
this.setState({
loading: false,
});
}, 500);
}
cancel(e, key) {
this.clickedCancel = true;
e.preventDefault();
const { data } = this.state;
const newData = data.map(item => ({ ...item }));
const target = this.getRowByKey(key, newData);
if (this.cacheOriginData[key]) {
Object.assign(target, this.cacheOriginData[key]);
delete this.cacheOriginData[key];
}
target.editable = false;
this.setState({ data: newData });
this.clickedCancel = false;
}
render() {
const columns = [
{
title: '字段名',
dataIndex: 'name',
key: 'name',
render: (text, record) => {
if (record.editable) {
return (
<Input
value={text}
autoFocus
onChange={e => this.handleFieldChange(e, 'name', record.key)}
onKeyPress={e => this.handleKeyPress(e, record.key)}
/>
);
}
return text;
},
},
{
title: '资产类型',
dataIndex: 'sub_name',
key: 'sub_name',
render: (text, record) => {
if (record.editable) {
return (
<Select
defaultValue={text}
onChange={e => this.handleFieldChange(e, 'sub_name', record.key)}
>
<Option value="1">是</Option>
<Option value="0">否</Option>
</Select>
);
}
return text;
},
},
{
title: ' ',
dataIndex: 'reg',
key: 'reg',
render: (text, record) => {
if (record.editable) {
return (
<Input
value={text}
onChange={e => this.handleFieldChange(e, 'reg', record.key)}
onKeyPress={e => this.handleKeyPress(e, record.key)}
/>
);
}
return text;
},
},
{
title: '操作',
key: 'action',
width: 108,
render: (text, record) => {
const { loading } = this.state;
if (!!record.editable && loading) {
return null;
}
if (record.editable) {
if (record.isNew) {
return (
<span>
<a onClick={e => this.saveRow(e, record.key)}>保存</a>
<Divider type="vertical" />
<Popconfirm title="是否要删除此行?" onConfirm={() => this.remove(record.key)}>
<a>删除</a>
</Popconfirm>
</span>
);
}
return (
<span>
<a onClick={e => this.saveRow(e, record.key)}>保存</a>
<Divider type="vertical" />
<a onClick={e => this.cancel(e, record.key)}>取消</a>
</span>
);
}
return (
<span>
<a onClick={e => this.toggleEditable(e, record.key)}>编辑</a>
<Divider type="vertical" />
<Popconfirm title="是否要删除此行?" onConfirm={() => this.remove(record.key)}>
<a>删除</a>
</Popconfirm>
</span>
);
},
},
];
const { loading, data } = this.state;
return (
<Fragment>
<Table
loading={loading}
columns={columns}
dataSource={data}
pagination={false}
rowKey="key"
size='small'
// rowClassName={record => (record.editable ? styles.editable : '')}
/>
<Button
style={{ width: '100%', marginTop: 16, marginBottom: 8 }}
type="dashed"
onClick={this.newMember}
icon="plus"
>
添加
</Button>
</Fragment>
);
}
}
export default TableForm;
table表单的使用
import TableForm from './tableForm'; tableChange = val => { console.log("e3e",val); this.setState({ tableVal: val }); // ref={(c)=>{this.searchForm=c}} form上添加这句,下面方便直接赋值给外层的表单 // this.searchForm.setFieldsValue({"assetTwo":vale}) }; const tableData = []; // 使用部分 <FormItem> {getFieldDecorator('assetTwo')( <div style={{ border: '1px solid #ccc' }}> <TableForm value={tableData} onChange={this.tableChange} // onChange={(val) => setFieldsValue({[`assetTwo`]: val, })} /> </div> )} </FormItem>

浙公网安备 33010602011771号