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




