搜索

AntdFormBattle


发布时间: 2022-11-24 21:23:00    浏览次数:35 次

v3


缘起

1亿年没写缘起了,但这次我一定要写。Form表单,让我的眼泪流尽了。数据交互方面,和React的Hooks还是有点小坑的,尤其是初始化的时候。昨天碰到的问题是,初始化之后,输入框无法输入,选择框无法选择,解决方法是降低层级,FormItem就直接用列表渲染出来。

今天碰到的问题是,动态渲染的列表无法对应上,对象转数组的方法报错。这里我是扩充了数组长度,来满足对象的生成,最后再清除列表中的空对象。

还有一点,就是rule校验对象,这个明天再补充。

2022-11-10 已补充validator的使用

1. 数据初始化

Form表单中有几个FormItem,传入的数据就要给什么,这是最容易明白的数据交互。

useEffect(() => {
    const { bankAccountInfo, ...others } = enterpriseSet;

    if (bankAccountInfo) {
      // 数组转为对象值
      const afterFormatInfo = bankAccountInfo.reduce((prev, cur, index) => {
        prev[`bank${index}`] = cur.bankEnglishShort;
        prev[`bankAccount${index}`] = cur.bankAccountNumber;
        return prev;
      }, {});
      const temp = { ...others, ...afterFormatInfo };
      setFieldsValue(temp);
    } else {
      const temp = { ...others };
      setFieldsValue(temp);
    }
  }, [enterpriseSet, setFieldsValue]);

这里重要的就是setFieldsValue方法,把传入值和Form相对接。

2. 数据交互

如果第一步做好,其实这一步就不用管了,antd会自己连接好。如果没搭上,那我的建议是,回到第一步初始化的时候,看看哪里出了毛病。

3. 表单项的增减

增加

push返回的是新字符串长度!!!

  const addBank = useCallback(() => {
    const newList = bankList;
    const lastNumber = newList[newList.length - 1] + 1;
    const newBankList = [...bankList, lastNumber];
    setBankList(newBankList);
  }, [bankList]);

减少

减少比增加难顶,需要注意其中缺失的数组边界情况,在对象转数组这一步需要考虑到

          <Form.Item label="银行">
            {getFieldDecorator(`bank${index}`, {
              rules: [
                {
                  required: true,
                  message: "请选择银行",
                },
              ],
            })(
              <Select placeholder="请选择">
                {bankListForUpdate.map(({ bankEnglishShort, bankName }) => {
                  return <Option value={bankEnglishShort}>{bankName}</Option>;
                })}
              </Select>
            )}
            {bankList.length > 1 ? (
              <Popconfirm
                title="你确定要删除这个账号吗?"
                onConfirm={() => removeBank(index)}
                onCancel={() => {}}
                okText="确定"
                cancelText="取消"
              >
                <Icon
                  className={styles["dynamic-delete-button"]}
                  type="delete"
                />
              </Popconfirm>
            ) : null}
          </Form.Item>

  const removeBank = useCallback(
    (k) => {
      const newBankList = bankList.filter((key) => key !== k);
      setBankList(newBankList);
    },
    [bankList]
  );

4. 表单数据校验

表单组件中直接调getFieldsValue函数

  const {  getFieldsValue } = form;

父组件中,使用ref,绑在表单组件上

        <Entry ref={formRef} bankListForUpdate={bankListForUpdate} />

  const formRef = useRef();

// ...
formRef.current.validateFieldsAndScroll((err, values) => {
      console.log(values);
      if (err) {
        console.log("校验不通过");
        return;
      }

5. 数据转换

bank0 bankAccount0 <-> [{bank: ..., bankAccount: ...}]

列表转对象

      // 数组转为对象值
      const afterFormatInfo = bankAccountInfo.reduce((prev, cur, index) => {
        prev[`bank${index}`] = cur.bankEnglishShort;
        prev[`bankAccount${index}`] = cur.bankAccountNumber;
        return prev;
      }, {});
      const temp = { ...others, ...afterFormatInfo };

对象转列表

export function getFormatArray(values) {
  return Object.keys(values)
    .reduce((prev, cur) => {
      const isAccount = cur.includes("bankAccount");
      const isBank = cur.includes("bank");
      const isKeyWord = isAccount || isBank;
      if (isKeyWord) {
        const curIndex = cur.replace(/bankAccount|bank/, "");
        // 根据curIndex大小加数组
        // cur = 3, prev中就需要为[{},{},{},{}] prev[3]要有值
        while (prev.length - 1 < curIndex) {
          prev.push({});
        }

        // 注意顺序,isAccount必定在isBank前
        if (isAccount) {
          prev[parseInt(curIndex)].bankAccountNumber = values[cur];
        } else {
          prev[parseInt(curIndex)].bankEnglishShort = values[cur];
        }
      }
      return prev;
    }, [])
    .filter((key) => Object.keys(key).length);
}

      // 将对象转换为数组值,注意最后空数组的处理
      const deliver = getFormatArray(values).map((value) => {
        value.bankName = bankListForUpdate.find(
          (key) => key.bankEnglishShort === value.bankEnglishShort
        ).bankName;
        return value;
      });

6. validator的使用

表单项中插入校验方法

        <Form.Item label="APPKey">
          {getFieldDecorator("appKey", {
            rules: [
              {
                required: true,
                validator: validattorForAppKey,
              },
            ],
          })(<Input allowClear placeholder="请输入" />)}
        </Form.Item>

校验方法

回调cb返回的是message校验出错提示内容,如为空,则不显示提示。

  // AppKey校验
  const validattorForAppKey = (rule, value, cb) => {
    const pattern = /[^A-Za-z0-9]/g;
    const notCrossReg = !!pattern.test(value);

    const isSuitableLength = value.length === 8 || value.length === 16;
    if (notCrossReg || !isSuitableLength) {
      cb("请输入8位或者16位AppKey");
    } else {
      cb();
    }
  };

如果在FormItem中先写了message内容,则会优先使用

                {
                  required: true,
                  validator: lengthValidator,
                  // pattern: /[A-Za-z0-9-]/,
                  message: "请输入9-35位的银行账号",
                },
  // 长度校验
  const lengthValidator = (rule, value, cb) => {
    try {
      const pattern = /[^A-Za-z0-9-]/g;
      const notCrossReg = !!pattern.test(value);

      const isSuitableLength = value.length >= 9 && value.length <= 35;
      if (notCrossReg || !isSuitableLength) {
        throw new Error("wrong");
      }
      cb();
    } catch (err) {
      cb(err);
    }
  };

正则校验

value非数字字母大小写与-,则notCrossReg则为true

      const pattern = /[^A-Za-z0-9-]/g;
      const notCrossReg = !!pattern.test(value);

7. 动态增减表单项bug

如果采用之前的bankList作为表单项增减的标杆,初始化的时候会有新的问题。所以还得采用antd自己的表单数据交互方法

这里我使用的时候死循环了,但之前看相关问题,似乎也有解决方法

img

动态增加form表单项中 我尝试用useState创建了一个BankList,但是后续遇到很多问题,比如初始化个数对不上。遂选择用form.getFieldValue('bankList')来创建动态表单长度的数组,但现在遇到的问题是 setFieldValue设置了bankList新的数值,在回显的时候,这个bankList的值都没了

我在想是用哪种来初始化 动态表单的项,是用useState,还是antd官网的getFieldValue,第一种我已经踩了坑,第二种正在踩坑

初始化的时候,bankList的值就没有附上去

1669022453607

  1. 删除后不保存 再次点击 不会存在
  2. 保存后再次点击是新的值

表单数据的获取接口,应该在渲染表单的时候,获取到最新的!!!我用redux是给自己挖坑了!

表格无数据时更换背景图,不用ConfigProvider这么麻烦

如何修改antd表格默认的暂无数据图标 - 简书 (jianshu.com)

附录

二次封装Antd中的Form,根据配置项生成表单 - 掘金 (juejin.cn)

免责声明 AntdFormBattle,资源类别:文本, 浏览次数:35 次, 文件大小:-- , 由本站蜘蛛搜索收录2022-11-24 09:23:00。此页面由程序自动采集,只作交流和学习使用,本站不储存任何资源文件,如有侵权内容请联系我们举报删除, 感谢您对本站的支持。 原文链接:https://www.cnblogs.com/lepanyou/p/16923381.html