ProComponents之EditableProTable-可编辑表格
对于初次使用ProComponents组件库的同学来说,官方文档过于复杂,本教程是帮助大家利用ProComponents库中的可编辑表格完成一个简答可编辑树形结构表格
EditableProTable基础属性配置:
rowKey="id" // 表格中每一行数据的key,要行数据中存在的属性名
actionRef={actionRef} // 定义行为实例,可用于后序新增数据
headerTitle="可编辑表格" // 表格的表题
recordCreatorProps={false} // 表格自带的新增按钮,设置为false不显示
columns={columns} // 表格表头
request={getData}// 可用于发起网请求获取表格数据 试例如下
// const getData = async (params: ApiType.ReqApiData) => {
// const res = await selectApiInfoByPage(params);
// return {
// data: res.data.records.map(item => ({ ...item, key: item.id })),// 要渲染的表格数据
// total: res.data.total, // 表格的条数,要分页就一定要返回
// success: true, // 表示数据是否请求成功,一般设置为true
// }
// }
value={dataSource} // 表格的数据
onChange={setDataSource} // 表格数据发生变化时调用
// 以上是高级表格的通用配置,以下是可编辑表格的一些配置
editable={{
form, // 设置表单实例,用于表单验证
editableKeys, // 当前在编辑的行的key
onSave: async (rowKey, data, row) => {
// 点击保存时调用
console.log(rowKey, data, row);
},
onChange: setEditableRowKeys, // 编辑行发生变化时调用的方法
actionRender: (row, config, dom) => [dom.save, dom.cancel], // 编辑时自定义操作按钮
}}
表头columns 常见配置:
const columns: ProColumns<DataSourceType>[] = [
{
dataIndex: 'name', // 表格对应的数据字段名
title: "参数名", // 表格表头名
ellipsis: true, // 是否开启自动缩进
},
{
dataIndex: 'type',
title: "参数类型",
ellipsis: true,
valueType: "select", // 数据类型,编辑时显示对应表单,默认text显示input输入框,select显示下拉框
valueEnum: { // 数据枚举
"String": "String",
"Int": "Int",
"Float": "Float",
"Array": "Array",
"Object": "Object"
},
formItemProps: { // 表单项配置
validateTrigger: "onChange", // 验证时机 onChange 改变时验证 onBlur 失去焦点时验证 onSubmit 提交时验证
rules: [ // 表单验证
{
required: true, // 是否必填
message: '此项为必填项', // 错误提示
},
{
validator(rule, value, callback) {
// 自定义验证
if (value === "Int") {
callback("Int 类型已停用,请选择其他类型"); // 返回错误信息
}
callback(); // 验证通过
},
}
],
},
},
]
actionRef新增行方法配置:
// 添加到最后一条
actionRef.current?.addEditRecord?.(
{
id: (Math.random() * 1000000).toFixed(0), // 新增数据的key,必填且唯一
name: '新的一行',
}
);
// 添加到指定父级下
actionRef.current?.addEditRecord?.(
{
id: (Math.random() * 1000000).toFixed(0),// 新增数据的key,必填且唯一
name: '新的一行',
},
{
parentKey: record.id, // 指定父级的key
//position?: "top" | "bottom" | undefined; // 添加的位置顶部或者底部(同一层级)
//newRecordType?: "dataSource" | "cache" | undefined; // 添加的方式,即一开始保存的发生,,保存到dataSource已有数据中或者cache缓存中
}
);
建议:
ProComponents的文档过于复杂,大家有时候看不懂,可以ctrl+鼠标左键点击代码,查看源码,看看可以传哪些参数,还有就是可以结合 Ant Design 的文档查看,应为ProComponents是基于Ant Design封装的,Ant Design中的很多属性ProComponents中也同样可以用到
试例代码:
import type { ActionType, ProColumns } from '@ant-design/pro-components';
import {
EditableProTable,
useRefFunction
} from '@ant-design/pro-components';
import { Button, Form, Space, message } from 'antd';
import React, { useRef, useState, forwardRef, useImperativeHandle } from 'react';
import { Typography } from 'antd';
const { Title } = Typography;
// 表格字段类型
type DataSourceType = {
id: React.Key;
name?: string | undefined;
address?: string | undefined;
type?: string | undefined;
requried?: boolean | undefined;
defaultValue?: string | undefined;
desc?: string | undefined;
children?: DataSourceType[] | undefined;
}
// 表格默认数据
const defaultData: DataSourceType[] = [
{
id: "0",
name: '活动名称一',
address: '活动区域一',
type: 'Object',
requried: true,
defaultValue: 'string',
desc: '这个活动真好玩',
children: [
{
id: "2",
name: '活动名称er',
address: '活动区域一',
type: 'String',
requried: true,
defaultValue: 'string',
desc: '这个活动真好玩',
},
]
},
{
id: "1",
name: '活动名称san',
address: '活动区域一',
type: 'Array',
requried: true,
defaultValue: 'string',
desc: '这个活动真好玩',
},
];
const loopDataSourceFilter = (
data: readonly DataSourceType[],
id: React.Key | undefined,
): DataSourceType[] => {
return data
.map((item) => {
if (item.id !== id) {
if (item.children) {
const newChildren = loopDataSourceFilter(item.children, id);
return {
...item,
children: newChildren.length > 0 ? newChildren : undefined,
};
}
return item;
}
return null;
})
.filter(Boolean) as DataSourceType[];
};
export default forwardRef((props: { tableTitle: string, columns: ProColumns<DataSourceType>[] }, ref: React.ForwardedRef<any>) => {
const actionRef = useRef<ActionType>(); // 行为实例,可用于后序新增等数据
const [editableKeys, setEditableRowKeys] = useState<React.Key[]>([]); // 当前编辑行
const [dataSource, setDataSource] = useState<readonly DataSourceType[]>([]); // 表格数据
const [form] = Form.useForm(); // 表单实例
// 删除行方法 传入当前行数据
const removeRow = useRefFunction((record: DataSourceType) => {
// 树形结构删除某行数据 loopDataSourceFilter(原始数据,删除行id)
setDataSource(loopDataSourceFilter(dataSource, record.id));
});
// 表格表头
const columns: ProColumns<DataSourceType>[] = [
{
dataIndex: 'name', // 表格对应的数据字段名
title: "参数名", // 表格表头名
ellipsis: true, // 是否开启自动缩进
},
{
dataIndex: 'type',
title: "参数类型",
ellipsis: true,
valueType: "select", // 数据类型,编辑时显示对应表单,默认text显示input输入框,select显示下拉框
valueEnum: { // 数据枚举
"String": "String",
"Int": "Int",
"Float": "Float",
"Array": "Array",
"Object": "Object"
},
formItemProps: { // 表单项配置
validateTrigger: "onChange", // 验证时机 onChange 改变时验证 onBlur 失去焦点时验证 onSubmit 提交时验证
rules: [ // 表单验证
{
required: true, // 是否必填
message: '此项为必填项', // 错误提示
},
],
},
},
{
dataIndex: 'required',
title: "是否必填",
ellipsis: true,
render: (text: any) => { // 自定义渲染内容
return text ? "是" : "否"
}
},
{
dataIndex: "defaultValue",
title: "默认值",
ellipsis: true,
},
{
dataIndex: "desc",
title: "参数说明",
ellipsis: true,
},
{
title: '操作',
valueType: 'option',
width: 250, // 表格列宽度
render: (text, record, _, action) => [
<Button
type="primary"
key="editable"
onClick={() => {
action?.startEditable?.(record.id);
}}
>
编辑
</Button>,
<Button
type="primary"
key="delete"
onClick={() => {
removeRow(record);
}}
>
删除
</Button>,
(record.type === "Array" || record.type === "Object") && <Button type="primary" onClick={() => {
actionRef.current?.addEditRecord?.(
{
id: (Math.random() * 1000000).toFixed(0),
name: '新的一行',
},
{
parentKey: record.id
}
);
}}>添加下级</Button>,
],
},
];
const onSave = () => {
if (editableKeys.length) {
message.error('请先保存参数')
return [false];
}
return [true, dataSource];
}
// 把保存数据方法暴露出去,给父级使用
useImperativeHandle(ref, () => {
return {
onSave
}
})
return (
<>
<EditableProTable<DataSourceType>
rowKey="id"// 表格中每一行数据的key,要行数据中存在的属性名
scroll={{
x: 960,
}}
actionRef={actionRef} // 定义行为实例,可用于后序新增数据
// 表格的表题
headerTitle={<Space>
<Title level={4}>{props.tableTitle}</Title>
<Button
type="primary"
onClick={() => {
actionRef.current?.addEditRecord?.(
{
id: (Math.random() * 1000000).toFixed(0),
name: '新的一行',
}
);
}}
>
新增参数
</Button>
<Button onClick={onSave}>保存</Button>
</Space>}
maxLength={5}
// 表格自带的新增按钮,设置为false不显示
recordCreatorProps={false}
columns={columns}
// 可用于发起网请求获取表格数据
request={async () => ({
data: defaultData,
total: 3,
success: true,
})}
value={dataSource} // 表格的数据
onChange={setDataSource} // 表格数据发生变化时调用的方法
// 以上是高级表格的通用配置,以下是可编辑表格的一些配置
editable={{
form, // 设置表单实例,用于表单验证
editableKeys, // 当前在编辑的行的key
onSave: async (rowKey, data, row) => {
// 点击保存时调用
console.log(rowKey, data, row);
},
onChange: setEditableRowKeys, // 编辑行发生变化时调用的方法
actionRender: (row, config, dom) => [dom.save, dom.cancel], // 编辑时自定义操作按钮
}}
/>
</>
);
});