react Antd 表格+可编辑行配置

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 是用来判断单元格内容应该是 输入框还是数值框,这部分在本次示例中没有用到,这里仅仅是提及一下。

\color{CadetBlue}{ 事实上官方文档API也没有谈及-列的属性 editing }
表格 Table - Ant Design,此处可点击自己查看
\color{CadetBlue}{其实他非常重要。}
\color{CadetBlue}{它用来表示当前单元格内容是否是编辑状态}
\color{CadetBlue}{而动态控制这个值的就是上面columns 数组提到的 editable 值)}
而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() 更改值。
{\color{red}{\text{部分代码细节不讲,自己能看懂}}}

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中::::

{\color{red}{\text{值得注意的是,想在table中编辑内容,得加 入Form表单元素 ,把 table 组件包裹 }}}

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>
        </>
    )
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,273评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,349评论 3 398
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,709评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,520评论 1 296
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,515评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,158评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,755评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,660评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,203评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,287评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,427评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,122评论 5 349
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,801评论 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,272评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,393评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,808评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,440评论 2 359

推荐阅读更多精彩内容