Ant Design Pro-EditableProTable 使用实例
还在为产品鬼马行空的想象力画出的一些离谱之极的可编辑表格而烦恼吗
只要掌握以下几点就可以为所欲为的调教EditableProTable组件啦βヾ(,,・∇・,)
- 使用name绑定到表单上, 虽然提供了value以及onChange但操作数据及表单联动起来极为麻烦
- 使用formItemProps配置该录入组件Form.Item的属性,例如getValueProps,getValueFromEvent等, 参照antd的Form.Item属性
- 使用fieldProps配置表单内录入组件的属性,例如onChange,onBlur等,具体录入组件可用属性参考antd的官方文档
官方文档介绍
属性 | 描述 | 内容 | 默认值 |
---|---|---|---|
fieldProps | 查询表单的 props,会透传给表单项,如果渲染出来是 Input,就支持 input 的所有 props,同理如果是 select,也支持 select 的所有 props。也支持方法传入 | (form,config)=>Record | Record | - |
formItemProps | 传递给 Form.Item 的配置,可以配置 rules,但是默认的查询表单 rules 是不生效的。需要配置 ignoreRules | (form,config)=>formItemProps | formItemProps | - |
源码:
import type { ProColumns } from '@ant-design/pro-table';
import { EditableProTable } from '@ant-design/pro-table';
import { hooks } from '@wove/react';
import { Button, Form } from 'antd';
import { nanoid } from 'nanoid';
import React, { useEffect } from 'react';
type DataSourceType = {
key: React.Key;
title?: string;
steps?: { name?: string }[];
type?: number;
descTemp?: string;
decs?: string;
state?: string;
created_at?: string;
children?: DataSourceType[];
};
const initialValues: { editableData: DataSourceType[] } = {
editableData: [
{
key: nanoid(),
title: '活动名称1',
type: 1,
state: 'down',
steps: [{ name: '第一步' }, { name: '第二步' }],
},
],
};
export const TableDemo = () => {
const [form] = Form.useForm<{ editableData: DataSourceType[] }>();
// 全表可编辑
const editableKeys = Form.useWatch('editableData', form)?.map((item) => item.key);
useEffect(() => {
form.setFieldsValue(initialValues);
}, []);
// 上移
const onUpClick = hooks.useCallbackRef((index) => {
const oldEditableData = form.getFieldValue('editableData');
const editableData = [...oldEditableData];
editableData[index] = editableData.splice(index - 1, 1, editableData[index])[0];
form.setFieldValue('editableData', editableData);
});
// 下移
const onDownClick = hooks.useCallbackRef((index) => {
const oldEditableData = form.getFieldValue('editableData');
const editableData = [...oldEditableData];
editableData[index] = editableData.splice(index + 1, 1, editableData[index])[0];
form.setFieldValue('editableData', editableData);
});
const columns: ProColumns<DataSourceType>[] = [
// 数据展示
// readonly: true 的render处理级别为 renderFormItem > renderText 不会显示render
{
title: '活动名称',
dataIndex: 'title',
readonly: true,
// renderFormItem: () => 'renderFormItem', // 优先处理
// renderText: () => 'renderText',
// render: () => 'render', // 不会显示
},
// 对象数组类型的数据无法使用readonly: true展示
// 数据无法转化会抛出异常
// Error : Objects are not valid as a React child (found: object with keys {name}). If you meant to render a collection of children, use an array instead.
// 此时可以使用 editable: false,
{
title: '活动步骤',
dataIndex: 'steps',
editable: false,
render: (dom, config) => {
console.log(dom); // 对象数组
return config.steps?.map((step, i) => <p key={i}>{step.name}</p>);
},
},
// 数据录入
// input
{
title: '活动名称',
dataIndex: 'title',
// 必填校验
formItemProps: {
rules: [{ required: true, message: '请输入!' }],
},
},
// select
{
title: '活动类型',
dataIndex: 'type',
valueType: 'select',
// 选项推荐写法 数据录入组件有options属性的都可以用
fieldProps: {
options: [
{ value: 1, label: '类型1' },
{ value: 2, label: '类型2' },
],
},
// 官网实例写法(不是很推荐 写法复杂且限制字符串数据类型):
// valueEnum: {
// one: { text: '类型1', status: '1' },
// two: { text: '类型2', status: '2' },
// three: { text: '类型3', status: '3' },
// },
},
// switch
{
title: '状态',
dataIndex: 'state',
initialValue: 'up',
valueType: 'switch',
fieldProps: {
checkedChildren: '上架',
unCheckedChildren: '下架',
},
// switch绑定boolean值只有true/false 可以使用getValueProps和getValueFromEvent再加工
// 其他录入组件都同理
formItemProps: {
getValueProps: (value) => ({ value: value == 'up' }),
getValueFromEvent: (value) => (value ? 'up' : 'down'),
},
},
// 联动
{
title: '活动描述模板',
dataIndex: 'descTemp',
valueType: 'select',
fieldProps: (form, config) => ({
options: [
{ value: 1, label: '模板1' },
{ value: 2, label: '模板2' },
],
onChange: (changeValue) => {
console.log('switch onchange changeValue =', changeValue);
// {type, isEditable, rowKey, rowIndex, entity}
console.log(config);
// 可以直接拿到数据
const descTemp = form.getFieldValue(['editableData', config.rowIndex, 'descTemp']);
// 联动数据
form.setFieldValue(['editableData', config.rowIndex, 'decs'], '描述模板' + descTemp);
},
}),
},
{
title: '描述',
dataIndex: 'decs',
readonly: true,
},
// 不展示列
{
title: '描述',
hideInTable: true,
dataIndex: 'decs',
readonly: true,
},
// valueType: 'option'
// 这里配置非编辑状态的操作
// 编辑状态的操作 在表格editable属性的actionRender属性配置
{
title: '操作',
valueType: 'option',
render: () => {
return null;
},
},
];
return (
<Form form={form}>
<EditableProTable<DataSourceType>
headerTitle="可编辑表格"
columns={columns}
scroll={{ x: 'max-content' }}
rowKey="key"
name="editableData" // 绑定到表单上方便管理
recordCreatorProps={{
record: {
key: nanoid(), // 必须唯一
},
}}
editable={{
type: 'multiple',
editableKeys,
// 操作
actionRender: (row, config, defaultDoms) => {
console.log(row, config);
return [
<Button
type="link"
style={{ padding: 0 }}
disabled={config.index == 0}
onClick={onUpClick.bind(null, config.index)}
>
上移
</Button>,
<Button
type="link"
style={{ padding: 0 }}
disabled={config.index == editableKeys.length - 1}
size="small"
onClick={onDownClick.bind(null, config.index)}
>
下移
</Button>,
defaultDoms.delete,
];
},
}}
/>
</Form>
);
}
效果展示:
5.6 更新上下移动
tips:上下移动和表格校验不能同时使用,有校验的字段会丢失,原因还未知(つД`)・゚・(つД`)・゚・
参考
https://procomponents.ant.design/components/editable-table
https://ant.design/components/form-cn