我是 React 新手,正在尝试 ant design。我需要构建一个多步骤表单,其中每个步骤都有几个字段,最后一步将有一个提交按钮。这将使用 antd 的 useForm 钩子。我不想使用任何其他插件,例如 antd-form-builder 等。
我面临的问题是,在多步骤表单中,在最后一步,当我按提交时,最后一步的表单数据可用,而先前步骤的数据不可用。我认为这可能是因为当我移动到“下一步”时,该步骤在 DOM 中被替换。
有没有更简单的方法来获取最后一步所有表单的数据?
我已经为示例准备了一个codesandbox。提交后请参阅控制台。
https://codesandbox.io/s/cool-mcnulty-or8jw
感谢您的帮助!
虽然上面的答案有效,但我不喜欢使用 CSS 来隐藏和显示步骤,因为它违背了 React 仅渲染所需组件的目的。
Antd 实际上在其文档中有一个内置的方法来处理这个问题。您所需要做的就是更新以下代码。
const formData = form.getFieldsValue();
到
const formData = form.getFieldsValue(true);
这将返回所有字段的值,而不仅仅是隐藏字段的值,请参阅其文档:https://ant.design/components/form/#API;
是的,这是因为当你没有在 DOM 中显示步骤时,你的步骤就会被破坏。
将步骤添加到步骤数组中,如下所示:
const steps = [
{
step: 1,
title: "Step1",
content: <Step1Form />
},
{
step: 2,
title: "Step2",
content: <Step2Form />
}
];
然后在你的css文件中定义一个新类:
.hidden { display: none; }
最后,在您的
StepPanel.js
文件中更改步骤的渲染方法。我们将渲染所有步骤:
{props.steps.map((item) => (
<div
className={`steps-content ${
item.step !== activeStep + 1 && "hidden"
}`}
>
{item.content}
</div>
))}
如您所见,我们正在检查每个步骤的步骤编号是否等于当前活动步骤。您可以在此处更改沙箱的分叉版本。
感谢所有答案这个和这个 我从中受益匪浅,并通过更新的 9-2024 和 antd 5.20 增强了答案
主要思想是 在主组件中添加表单,并在其他组件中单独添加表单列表
首先,为步进器和内容创建 2 个列表
const Page = () => {
//mainForm.tsx
//create 2 lists for stepper and content
const items: StepsProps["items"] = [
{
title: "First",
},
{
title: "Second",
},
{
title: "Last",
},
];
const stepperItems = [
{
title: "First",
content: <DescriptionServiceForm />,
},
{
title: "Second",
content: <PriceAndAddons />,
},
{
title: "Last",
content: "Last-content",
},
];
const [form] = Form.useForm();
const [current, setCurrent] = useState(0);
//if you want to save form values in useState or you can use form.getFieldsValue(true)
const [formValues, setFormValues] = useState<any>({});
const next = () => {
//use this to return all form lists
const values = form.getFieldsValue(true);
//or this to return every form list alone and store it in state
const values = form.getFieldsValue();
setFormValues((prev: any) => ({ ...prev, ...values }));
setCurrent(current + 1);
};
const prev = () => {
setCurrent(current - 1);
};
return (
<Form form={form}>
<Steps
size="small"
current={0}
items={items}
/>
<div>
{stepperItems[current].content}
{current < stepperItems.length - 1 && (
<Button type="primary" onClick={() => next()}>
Next
</Button>
)}
{current === stepperItems.length - 1 && (
<Button type="primary">
Done
</Button>
)}
{current > 0 && (
<Button onClick={() => prev()}>
Previous
</Button>
)}
</div>
</Form>
)};
export default Page;
实现表单的第 1 部分,以在第一步中将其显示为活动状态
const DescriptionServiceForm = () => {
return (
<Form.List name="description">
{(fields, operation, meta) => (
<div className="flex gap-5 w-full">
<Form.Item
label="firstName"
name="first_name"
>
<Input />
</Form.Item>
<Form.Item
label="lastName"
name="last_name"
>
<Input />
</Form.Item>
</div>
)}
</Form.List>
)}
export default DescriptionServiceForm;
实现表单的第 2 部分,以在第二步中将其显示为活动状态
const PriceAndAddons = () => {
return (
<Form.List name="description">
{(fields, operation, meta) => (
<div className="flex gap-5 w-full">
<Form.Item
label="email"
name="email"
>
<Input />
</Form.Item>
</div>
)}
</Form.List>
)}
export default PriceAndAddons;
最终输出将表单的每个部分分类到一个以 formList 名称命名的对象中
values = {
"description": {
"first_name": "Ahmed",
"last_name": "Korany"
},
"priceAndAddons": {
"email": "[email protected]"
}
}