Ant Design Pro-EditableProTable 使用实例(数据联动,特殊处理等)

Ant Design Pro-EditableProTable 使用实例
还在为产品鬼马行空的想象力画出的一些离谱之极的可编辑表格而烦恼吗
只要掌握以下几点就可以为所欲为的调教EditableProTable组件啦βヾ(,,・∇・,)

  1. 使用name绑定到表单上, 虽然提供了value以及onChange但操作数据及表单联动起来极为麻烦
  2. 使用formItemProps配置该录入组件Form.Item的属性,例如getValueProps,getValueFromEvent等, 参照antd的Form.Item属性
  3. 使用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>
  );
}

效果展示:


image.png

5.6 更新上下移动
tips:上下移动和表格校验不能同时使用,有校验的字段会丢失,原因还未知(つД`)・゚・(つД`)・゚・

参考
https://procomponents.ant.design/components/editable-table
https://ant.design/components/form-cn

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。