我正在尝试让表单步骤易于导航。必须允许用户通过单击以前的表单步骤返回,如果目标步骤和中间的所有内容都已填写且有效,则前进。
我通过使用类似这样的方法使它工作起来,但这个方法的问题是validateFields()只检查当前步骤的表单,所以我可以填写,比方说第一步,然后向前跳8步,因为validateFields()只验证当前步骤,认为一切都很好。
form.validateFields()
.then(() => {
setCurrentStep(step);
})
.catch((err) => {
console.log(err);
return;
});
所以我尝试让validateFields()
接受一个包含需要检查的每个表单字段名的数组。但是,我找不到任何关于这种实现的文档,下面的文档总是导致解析。
const handleStepChange = (step) => {
// let user go back to previous steps
if (step <= currentStep) {
setCurrentStep(step);
return;
}
// let user go forward if everything is valid
// if not, force user to use "next step" button
form.validateFields(FORM_FIELDS) // FORM_FIELDS is an array that keeps field names
.then(() => {
setCurrentStep(step);
})
.catch((err) => {
console.log(err);
return;
});
};
这是我大致整理的方法:
const [form] = Form.useForm();
const [currentStep, setCurrentStep] = useState(0);
const initialSteps = {
form,
step: (val) => setCurrentStep(val),
nextStep: () => setCurrentStep((prev) => prev + 1),
};
const [steps] = useState([
{
title: 'Personal',
content: <PersonalForm {...initialSteps} />,
},
{
title: 'Details',
content: <DetailsForm {...initialSteps} />,
},
{
title: 'Contact',
content: <ContactForm {...initialSteps} />,
}])
return <Steps
size="small"
current={currentStep}
direction="vertical"
onChange={(current) => handleStepChange(current)}
>
{steps.map((item, index) => (
<Step status={item.status} key={item.title} title={item.title} />
))}
</Steps>
我如何验证确保验证每一个表单字段被卸载,未填写,未触及等?
编辑:我也尝试过分别访问每个步骤的表单对象,希望每个表单对象都包含自己的表单字段,但也没有成功
const handleStepChange = (step) => {
// let user go back to previous steps
if (step <= currentStep) {
setCurrentStep(step);
return;
}
// let user go forward if target step and steps in between are filled in
const validationFields = [];
const stepsInbetween = [];
for (let i = 0; i < step - currentStep; i++) {
const stepCursor = steps[currentStep + i];
stepsInbetween.push(stepCursor);
const stepCursorFields = STEP_FIELDS[stepCursor.content.type.name];
validationFields.push(...stepCursorFields);
}
let isValid = true;
stepsInbetween.forEach((s) => {
s.content.props.form
.validateFields()
.then(() => {})
.catch(() => (isValid = false));
});
if (isValid) setCurrentStep(step);
};
2条答案
按热度按时间qkf9rpyu1#
你应该使用
Form
元素,而不是把每个字段放在一起。Ant Design的表单已经有了内置的数据收集、验证,并对每个字段执行验证,不管它们是否被触摸。这是一个实现
Form
的框架表单。你需要用Form.Item
Package 每个字段,然后在Form.Item
中传入一个对象,作为rules
,其中required=True
是条目之一。听起来比实际情况更复杂,所以这里有一个片段:将检查和验证由
<Form.Item />
Package 的任何字段,其中required: true
在其规则中。您还可以根据每个字段的要求使用设置rules
使其更加复杂。示例:从它的documentation,
表单将自动收集和验证表单数据。
因此,只需依靠
Form
组件根据您在每个Form.Item
上指定的规则来处理验证,就可以保存大量的自定义代码。编辑1
根据评论中的其他信息,由于您提到您已经使用了
<Form.Item>
,这将有助于在用户通过useEffect()
钩子导航到其他页面时强制运行验证。如果currentStep
被更新(通过setCurrentStep
),则在useEffect()
主体中运行代码。n9vozmp42#
这是因为form对象的
validateFields
方法只验证当前在DOM中呈现的字段。以下是一个解决方法:
渲染所有对象,但仅使选定对象可见
然后在构成窗体的组件中: