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

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