Antd-ProComponents中的EditableProTable无法在子行继续新增子子行的临时解决方案

简介: Antd-ProComponents中的EditableProTable无法在子行继续新增子子行的临时解决方案

一、BUG效果如下


0fcfd94170ae405382754de6f53bbe2b.gif

点击后报错:


6e69cdac94af411c904aeb7e9759f929.png

二、复现代码


import { EditableProTable } from '@ant-design/pro-table';
import React, { useState } from 'react';
const defaultData: any = new Array(3).fill(1).map((_, index) => {
  return {
    id: (Date.now() + index).toString(),
    title: `活动名称${index}`,
    decs: '这个活动真好玩',
    state: 'open',
    created_at: '2020-05-26T09:42:56Z',
  };
});
export default () => {
  const [editableKeys, setEditableRowKeys] = useState<React.Key[]>(() =>
    defaultData.map((item) => item.id),
  );
  const [dataSource, setDataSource] = useState<any[]>(() => defaultData);
  const columns: any = [
    {
      title: '活动名称',
      dataIndex: 'title',
      width: '30%',
      formItemProps: {
        rules: [
          {
            required: true,
            whitespace: true,
            message: '此项是必填项',
          },
          {
            message: '必须包含数字',
            pattern: /[0-9]/,
          },
          {
            max: 16,
            whitespace: true,
            message: '最长为 16 位',
          },
          {
            min: 6,
            whitespace: true,
            message: '最小为 6 位',
          },
        ],
      },
    },
    {
      title: '状态',
      key: 'state',
      dataIndex: 'state',
      valueType: 'select',
      valueEnum: {
        all: { text: '全部', status: 'Default' },
        open: {
          text: '未解决',
          status: 'Error',
        },
        closed: {
          text: '已解决',
          status: 'Success',
        },
      },
    },
    {
      title: '描述',
      dataIndex: 'decs',
    },
    {
      title: '操作',
      valueType: 'option',
      width: 250,
      render: () => {
        return null;
      },
    },
  ];
  return (
    <>
      <EditableProTable<any>
        headerTitle="可编辑表格"
        columns={columns}
        rowKey="id"
        scroll={{
          x: 960,
        }}
        value={dataSource}
        onChange={setDataSource}
        recordCreatorProps={{
          newRecordType: 'dataSource',
          position: 'bottom',
          record: () => ({
            id: Date.now(),
          }),
        }}
        editable={{
          type: 'multiple',
          editableKeys,
          actionRender: (row, config, defaultDoms) => {
            return [defaultDoms.delete,
            <EditableProTable.RecordCreator
              parentKey={row.id}
              newRecordType='dataSource'
              position='bottom'
              record={{
                id: Date.now(),
              }}
            >
              <a>增加子行</a>
            </EditableProTable.RecordCreator>];
          },
          onValuesChange: (record, recordList) => {
            setDataSource(recordList);
          },
          onChange: setEditableRowKeys,
        }}
      />
    </>
  );
};


三、解决方案


自己写一个递归的方法将子行追加到选中行下即可,下面展示的是我项目中的代码,不能复制直接用,但思路是一样的。

首先在actionRender中自定义“增加子行”的操作按钮,其中addChildToSource为增加逻辑方法:

       actionRender: (row, _, dom) => [
            <a
              key="addChild"
              onClick={() => addChildToSource(row.id, type)}
            >
              增加子行
            </a>
          ],


addChildToSource代码如下:

  //增加子行
  const addChildToSource = (rowKey: any, type: string) => {
    let childRowKey = Date.now(); //rowkey的id不能重复,不然会回填异常
    editableKeys[type].push(childRowKey);
    let source = formRef.current.getFieldValue(`${type}_source`); //type_source为表格定义的formItem的name
    source = addChildToSourceFunc(source, rowKey, childRowKey, type);
    const _dict = {};
    _dict[`${type}_source`] = source;
    formRef.current.setFieldsValue(_dict);
    setEditableKeys({ ...editableKeys });
  };


上述方法调用的addChildToSourceFunc代码如下:


  //删除参数edit及子级edit
   const addChildToSourceFunc = (
    source: any,
    rowKey: any,
    childRowKey: any,
    type: string,
    childName: any = null,
  ) => {
    for (var i = 0; i < source.length; i++) {
      const sourceItem = source[i];
      if (sourceItem.id === rowKey) {
        if (!sourceItem.children) {
          sourceItem.children = [];
        }
        sourceItem.children.push({ id: childRowKey, required: true, param_type: 'string', name: childName });
        break;
      } else if (sourceItem.children) {
        addChildToSourceFunc(sourceItem.children, rowKey, childRowKey, type, childName,);
      }
    }
    return source;
  };


成功解决了该问题,解决后的效果:

399855d0864c4001bc36f206628c8828.gif

目录
相关文章
|
5月前
|
JavaScript
vue数据更新了但是页面不更新的解决方案
vue数据更新了但是页面不更新的解决方案
87 0
uniapp 全局数据(globalData)的设置,获取,更改
uniapp 全局数据(globalData)的设置,获取,更改
1966 0
|
9天前
|
前端开发 JavaScript UED
react或者vue更改用户所属组,将页面所有数据进行替换(解决问题思路)____一个按钮使得页面所有接口重新请求
在React或Vue中,若需在更改用户所属组后更新页面所有数据但不刷新整个页面,可以通过改变路由出口的key值来实现。在用户切换组成功后,更新key值,这会触发React或Vue重新渲染路由出口下的所有组件,从而请求新的数据。这种方法避免了使用`window.location.reload()`导致的页面闪烁,提供了更流畅的用户体验。
18 1
react或者vue更改用户所属组,将页面所有数据进行替换(解决问题思路)____一个按钮使得页面所有接口重新请求
|
2月前
|
JavaScript 前端开发
在Vue3+ElementPlus项目中实现一个简单的新增/移除行记录的小组件
在Vue 3和Element Plus项目中创建一个支持新增和移除行记录的简单表格组件。
152 0
|
3月前
|
监控 JavaScript Serverless
函数计算产品使用问题之如何部署一个未构建的Vue项目,并实现从Gitee仓库自动同步更新
函数计算产品作为一种事件驱动的全托管计算服务,让用户能够专注于业务逻辑的编写,而无需关心底层服务器的管理与运维。你可以有效地利用函数计算产品来支撑各类应用场景,从简单的数据处理到复杂的业务逻辑,实现快速、高效、低成本的云上部署与运维。以下是一些关于使用函数计算产品的合集和要点,帮助你更好地理解和应用这一服务。
|
5月前
|
JavaScript 数据库
【vue】vue2 数据回显取消编辑不修改原数据
【vue】vue2 数据回显取消编辑不修改原数据
160 1
|
5月前
|
存储 JavaScript 前端开发
uni-app 从vue3项目创建到Pinia管理数据全局使用 持久化存储数据 详细教程
uni-app 从vue3项目创建到Pinia管理数据全局使用 持久化存储数据 详细教程
|
5月前
|
JavaScript
vue列表信息展示中新增数据,与编辑数据页面复用,降低重复代码
vue列表信息展示中新增数据,与编辑数据页面复用,降低重复代码
226 2
|
5月前
|
移动开发 前端开发 JavaScript
动态获取新增的数据+项目实例介绍
动态获取新增的数据+项目实例介绍
83 0
|
5月前
|
存储 JavaScript
vue列表新增存储假数据
vue列表新增存储假数据
48 0