You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Ant Design中Form.List删除列表项时调用form.validateFields()校验失效问题求助

解决Ant Design Form.List删除项后重复值校验不触发的问题

我来帮你排查并解决这个问题,核心问题出在校验范围不对重复值校验逻辑有漏洞这两个地方,咱们一步步来修复:

1. 先修正删除后的校验范围

你当前调用的form.validateFields(['formList',0,'name'])只会校验列表的第一个项,但删除操作后需要校验整个formList的所有项,所以应该改成:

form.validateFields(['formList'])

这样会触发整个列表里所有表单项的校验,自然就会重新检查重复值了。

2. 修复重复值校验的逻辑漏洞

你的validator里有几个逻辑错误,导致重复值判断不准确:

  • getFieldValue("formList")返回的是对象数组(每个元素是{name: 'xxx'}),但你定义成了string[],类型不匹配
  • valuesTmp.findIndex((e) => e === value)这里,e是对象,value是字符串,永远找不到匹配项,导致splice操作无效

咱们换更准确的方式实现重复校验:通过当前项的索引排除自己,再检查其他项是否有重复值。修改后的validator如下:

({ getFieldValue, field }) => ({
  validator(_, value) {
    if (!value) {
      return Promise.resolve();
    }
    // 获取整个表单列表数据
    const formList = getFieldValue("formList") || [];
    // 当前项在列表中的索引(field.name是[当前项索引, 'name'])
    const currentItemIndex = field.name[0];
    // 检查除了当前项之外,是否有其他项的name和当前值重复
    const isDuplicated = formList.some(
      (item, index) => index !== currentItemIndex && item.name === value
    );
    return isDuplicated 
      ? Promise.reject("It's duplicated") 
      : Promise.resolve();
  },
})

3. 修正Form.Item的fieldKey配置

你之前的fieldKey={[fieldKey,"fieldKey"]}是错误的,应该和name对应,改成:

fieldKey={[fieldKey, "name"]}

这样Form才能正确关联字段的键值,避免校验时出现匹配错误。

完整修正后的代码

把这些修改整合起来,最终代码如下:

<Form.List name="formList">
  {(fields, { add, remove }, { errors }) => (
    <>
      {fields.map(({ key, name, fieldKey, ...restField }) => (
        <div key={key}>
          <Form.Item
            {...restField}
            name={[name, "name"]}
            fieldKey={[fieldKey, "name"]}
            validateTrigger={["onChange", "onBlur", "onFocus"]}
            rules={[
              { required: true, message: "please enter text" },
              {
                pattern: new RegExp(/^[\x00-\x7F]+$/),
                message: "please enter A-Z, a-z, 0-9"
              },
              ({ getFieldValue, field }) => ({
                validator(_, value) {
                  if (!value) {
                    return Promise.resolve();
                  }
                  const formList = getFieldValue("formList") || [];
                  const currentItemIndex = field.name[0];
                  const isDuplicated = formList.some(
                    (item, index) => index !== currentItemIndex && item.name === value
                  );
                  return isDuplicated 
                    ? Promise.reject("It's duplicated") 
                    : Promise.resolve();
                },
              }),
            ]}
          >
            <Input placeholder="Enter your name" />
          </Form.Item>
          <MinusCircleOutlined
            onClick={() => {
              remove(name);
              // 校验整个表单列表
              form.validateFields(['formList']);
            }}
          />
        </div>
      ))}
      <Form.Item>
        <Button type="dashed" onClick={() => add()} block icon={<PlusOutlined />}>
          Add Token
        </Button>
        <Form.ErrorList errors={errors} />
      </Form.Item>
    </>
  )}
</Form.List>

这样修改后,删除列表项时就会触发整个列表的校验,重复值的判断也会准确生效了。

内容的提问来源于stack exchange,提问作者Boss

火山引擎 最新活动