Antd 基础表格很容易设置,但是对于可编辑的行的配置,确实需要一点细心。对于刚入门,或者不太懂这个配置的来说无疑是奔溃的。今天就来记录下一个简单的可编辑行配置的步骤。
表格需要的基础数据
Table 组件 Column组件
一个模拟数据的Array 一个 column 设置的 Array
其中 key 值只是用来标识数据的 key
editable 是用来判断 当前某行某列单元格内容是否处于正在编辑状态
const [data, setDataSource] = useState([
{
key: '1',
order: '1',
keyName: '连衣裙',
},
{
key: '2',
order: '2',
keyName: '裤子',
}
])
const columns = [
{
title: 'order',
editable: true,
dataIndex: 'order'
},
{
title: 'keyName',
editable: true,
dataIndex: 'keyName'
},
]
上边是基础数据。接下来根据 columns 数组来生成 对应表格的每一列的配置
此处利用map来操作
其中inputType 是用来判断单元格内容应该是 输入框还是数值框,这部分在本次示例中没有用到,这里仅仅是提及一下。
表格 Table - Ant Design,此处可点击自己查看
而isEditing 函数用来设置对应的 行数据 是否编辑状态,由 editingKey控制。那么 setEditingKey在哪里调用呢?
🍔🍗答: 每行数据最后加个 功能单元格 然后点击触发函数 即可(看下边!)
const [editingKey, setEditingKey] = useState(''); //初始化为空
const isEditing = (record) => record.key === editingKey;
const mergedColumns = columns.map((col) => {
if (!col.editable) {
return col;
}
return {
...col,
onCell: (record) => ({
record,
inputType: col.dataIndex === 'age' ? 'number' : 'text',
dataIndex: col.dataIndex,
title: col.title,
editing: isEditing(record), !!!!注意这里
}),
};
});
(有人可能蒙圈了,怎么又是行编辑又是列的属性的编辑editing?
🍔🍗答: 每一行数据有一个 key值, 当与 editingKey 相等,代表当前行数据处于编辑状态。editingKey 由 setEditingKey控制,用户调用setEditingKey('key?') 来控制某行要编辑 。而单元格由 editing 来配置编辑状态,
故而 record.key === editingKey 如果为 true 则 那一行的所有单元格 的 editing 都为 true,则实现整行都处于编辑状态)
功能单元格:::
上边的 columns 数组改写。增加 title 为 operation 的单元格
通过 每行的 Typography.Link 按钮-edit 函数来调用 setEditingKey() 更改值。
import { Form, Table, Input, InputNumber, Popconfirm, Typography } from 'antd'
const cancel = () => {
setEditingKey('');
};
const handleDelete = (key) => {
const newData = data.filter((item) => item.key !== key);
setDataSource(newData);
};
const edit = (record) => {
form.setFieldsValue({ //此处初始化form 组件的值
// key: '3',
order: '',
keyName: '',
...record,
});
setEditingKey(record.key); //此处更改 editingKey 值!!!
};
const columns = [
{
title: 'order',
editable: true,
dataIndex: 'order'
},
{
title: 'keyName',
editable: true,
dataIndex: 'keyName'
},
{
title: 'operation',
dataIndex: 'operation',
render: (_, record) => {
const editable = isEditing(record);
return editable ? (
<>
<Popconfirm title="Sure to delete?" onConfirm={() => handleDelete(record.key)}>
<a>Delete</a>
</Popconfirm>
<Popconfirm title="Sure to cancel?" onConfirm={cancel}>
<a>Cancel</a>
</Popconfirm>
</>
) : <Typography.Link disabled={editingKey !== ''} onClick={() => edit(record)}>
Edit
</Typography.Link>
}
}
]
上边都是 主要讲解其中的逻辑,接下来就是渲染UI table组件即可
设置form表单元素 样式组件
const EditableCell = ({
editing,
dataIndex,
title,
inputType,
record,
index,
children,
...restProps
}) => {
const inputNode = inputType === 'number' ? <InputNumber /> : <Input />;
return (
<td {...restProps}>
{editing ? (
<Form.Item
name={dataIndex}
style={{
margin: 0,
}}
rules={[
{
required: true,
message: `Please Input ${title}!`,
},
]}
>
{inputNode}
</Form.Item>
) : (
children
)}
</td>
);
};
把form 模板加入到 Table 的 components中::::
const [form] = Form.useForm();
<Form form={form} component={false}>
<Table
components={{
body: {
cell: EditableCell,
},
}}
columns={mergedColumns}
dataSource={data}
pagination={{ total: '50', showQuickJumper: true,
showSizeChanger: true,
pageSize: '5', size: "small" }}>
</Table>
</Form>
整个组件的完整代码如下:
import { Form, Table, Input, InputNumber, Popconfirm, Typography } from 'antd'
import { Button } from 'antd/lib/radio';
import React from 'react'
import { useState } from 'react';
const { Column, ColumnGroup } = Table
const EditableCell = ({
editing,
dataIndex,
title,
inputType,
record,
index,
children,
...restProps
}) => {
const inputNode = inputType === 'number' ? <InputNumber /> : <Input />;
return (
<td {...restProps}>
{editing ? (
<Form.Item
name={dataIndex}
style={{
margin: 0,
}}
rules={[
{
required: true,
message: `Please Input ${title}!`,
},
]}
>
{inputNode}
</Form.Item>
) : (
children
)}
</td>
);
};
export default function LeftCard() {
const [form] = Form.useForm();
const [editingKey, setEditingKey] = useState('');
const [data, setDataSource] = useState([
{
key: '1',
order: '1',
keyName: '连衣裙',
},
{
key: '2',
order: '2',
keyName: '裤子',
},
])
const columns = [
{
title: 'order',
editable: true,
dataIndex: 'order'
},
{
title: 'keyName',
editable: true,
dataIndex: 'keyName'
},
{
title: 'operation',
dataIndex: 'operation',
render: (_, record) => {
const editable = isEditing(record);
return editable ? (
<>
<Popconfirm title="Sure to delete?" onConfirm={() => handleDelete(record.key)}>
<a>Delete</a>
</Popconfirm>
<Popconfirm title="Sure to cancel?" onConfirm={cancel}>
<a>Cancel</a>
</Popconfirm>
</>
) : <Typography.Link disabled={editingKey !== ''} onClick={() => edit(record)}>
Edit
</Typography.Link>
}
}
]
const cancel = () => {
setEditingKey('');
};
const isEditing = (record) => record.key === editingKey;
const mergedColumns = columns.map((col) => {
if (!col.editable) {
return col;
}
return {
...col,
onCell: (record) => ({
record,
inputType: col.dataIndex === 'age' ? 'number' : 'text',
dataIndex: col.dataIndex,
title: col.title,
editing: isEditing(record),
}),
};
});
function pageChange(pagination, filters, sorter, extra) {
console.log(extra)
}
const handleDelete = (key) => {
const newData = data.filter((item) => item.key !== key);
setDataSource(newData);
};
const edit = (record) => {
form.setFieldsValue({
// key: '3',
order: '',
keyName: '',
...record,
});
setEditingKey(record.key);
};
return (
<>
<Form form={form} component={false}>
<Table
components={{
body: {
cell: EditableCell,
},
}}
columns={mergedColumns}
dataSource={data}
onChange={pageChange}
pagination={{ total: '50', showQuickJumper: true, showSizeChanger: true, pageSize: '5', size: "small" }}>
</Table>
</Form>
</>
)
}