Form.List
如何用antd的Form.List配合Table组件实现一个可编辑表格
快速访问
版本说明
Antd 4.X
实现思路
Form.List实现列表化的能力,布局排版使用Table组件- 在渲染
Table的每一列的内容上使用render自定义渲染表单项 Table的数据源项使用Form.List的fields数据进行填充
show code
Container.tsx
import React from "react";
import { Button, Form, Table, Input, FormInstance } from "antd";
import { ColumnType } from "antd/es/table/interface";
type TypeProps = {
form: FormInstance;
};
function formListTableColumns({
form,
remove
}: {
form: FormInstance;
remove: (index: number | number[]) => void;
}) {
const columns = [
{
title: "a",
dataIndex: "a",
render: (text, record, index) => {
return (
<Form.Item name={[record.name, "a"]}>
<Input />
</Form.Item>
);
},
width: 200
},
{
title: "b",
dataIndex: "b",
width: 200,
render: (text, record, index) => {
return (
<Form.Item name={[record.name, "b"]}>
<Input />
</Form.Item>
);
}
},
{
title: "c",
dataIndex: "c",
width: 200,
render: (text, record, index) => {
return (
<Form.Item name={[record.name, "c"]}>
<Input />
</Form.Item>
);
}
},
{
title: "d",
dataIndex: "d",
width: 200,
render: (text, record, index) => {
return (
<Form.Item name={[record.name, "d"]}>
<Input />
</Form.Item>
);
}
},
{
title: "e",
dataIndex: "e",
width: 200,
render: (text, record, index) => {
return (
<Form.Item name={[record.name, "e"]}>
<Input />
</Form.Item>
);
}
},
{
title: "f",
dataIndex: "f",
width: 200,
render: (text, record, index) => {
return (
<Form.Item name={[record.name, "f"]}>
<Input />
</Form.Item>
);
}
},
{
title: "操作",
dataIndex: "option",
width: 100,
fixed: "right",
render: (text, record, index) => {
return [
<Form.Item name={[record.name, "q"]} hidden key="q"></Form.Item>,
<Form.Item name={[record.name, "w"]} hidden key="w"></Form.Item>,
<Form.Item name={[record.name, "e"]} hidden key="e"></Form.Item>,
<Form.Item name={[record.name, "r"]} hidden key="r"></Form.Item>,
<Form.Item name={[record.name, "t"]} hidden key="t"></Form.Item>,
<Form.Item name={[record.name, "y"]} hidden key="y"></Form.Item>,
<Button
key="delete"
onClick={() => {
remove(record.name);
const formData = form.getFieldsValue();
/** 由于删除内容依旧会保留需要手动过滤,并重新赋值 */
const newPriceList = (formData?.list || []).filter(
(item: any) => {
if (!item.rowKey) {
return false;
}
return true;
}
);
form.setFieldsValue({ list: newPriceList });
}}
style={{ color: "#ff4d4f" }}
>
删除
</Button>
];
}
}
] as ColumnType<any>[];
return columns;
}
export default function (props: TypeProps) {
return (
<Form.List name="list">
{(fields, { add, remove }) => {
return (
<>
<Table
bordered
scroll={{ x: 960 }}
rowKey={"rowKey"}
pagination={false}
dataSource={fields}
size="small"
columns={formListTableColumns({ form: props.form, remove })}
/>
<Form.Item>
<Button
style={{ width: "100%", marginBottom: 200 }}
onClick={() => {
add({ rowKey: new Date().valueOf() });
}}
type="dashed"
>
+ 增加
</Button>
</Form.Item>
</>
);
}}
</Form.List>
);
}
代码解析
formListTableColumns
该方法接收form实现参数和Form.List的remove方法
在render中Form Item的name属性需要动态填入
<Form.Item name={[record.name, "f"]}>
// 这里填充表单内容
</Form.Item>
record.name是表示当前行的form名称,f是当前字段
App.tsx
import React from "react";
import Container from "./Container";
import { Form } from "antd";
export default function (props: any) {
const form = Form.useForm()[0];
return (
<div>
<Form form={form}>
<Container form={form} />
</Form>
</div>
);
}
代码解析
这里直接使用组件,传入form实例,便于其它表单操作
Form.List 如何动态校验
这里可以使用dependencies来接收需要监听变化的字段
dependencies={[['list', record.name, 'f']]} list 是当前form list的表单字段名称 ,record.name是行表单的名称,f 是表示的是字段,注意这里需要使用数组嵌套的方式表示