gpt4 book ai didi

javascript - 如何管理带有父字段和子字段的表单的显示

转载 作者:行者123 更新时间:2023-12-05 03:19:40 24 4
gpt4 key购买 nike

我正在 React 中构建一个多步骤表单(配置器),其中一些步骤具有子步骤。

Multi from UI

步骤(包括下拉菜单)是基于以下 JSON 结构创建的:

[
{
id: "step_a",
title: "Step A",
options: [
{
id: "1",
title: "Option 1",
child_steps: ["step_b"],
},
{
id: "2",
title: "Option 2",
child_steps: ["step_c"],
},
],
},
{
id: "step_b",
title: "Step B",
parent_step: "step_a",
options: [
{
id: "1",
title: "Option 1",
},
{
id: "2",
title: "Option 2",
},
],
},
{
id: "step_c",
title: "Step C",
parent_step: "step_a",
options: [
{
id: "1",
title: "Option 1",
child_steps: ["step_d"],
},
{
id: "2",
title: "Option 2",
},
],
},
{
id: "step_d",
title: "Step D",
parent_step: "step_c",
options: [
{
id: "1",
title: "Option 1",
},
{
id: "2",
title: "Option 2",
},
],
},
];

步骤中的每个下拉菜单都有选项。

  • 一些选项与子步骤有关。
  • 但是一些子步骤具有与其他子步骤相关的选项。

我正在努力实现以下 3 个要求的组合:

  1. 选择与子步骤连接的选项时,出现子步骤,并且同样适用于基础子步骤。
  2. 当您更改为顶级下拉列表中的另一个选项时,不仅该选项的子级应该折叠,而且底层子步骤的步骤也应该折叠。
  3. 只有选定字段和非折叠字段的表单输入应以(配置)状态存储(并稍后发布到服务器)。

App.js

import "./styles.css";
import steps from "./steps.js";
import Step from "./components/Step";

export default function App() {
return (
<div className="App">
<div className="steps">
{steps.map((step) => (
<Step key={step.id} step={step} />
))}
</div>
</div>
);
}

Step.js

import { ConfiguratorContext } from "../context/ConfiguratorContext"; // Holds configuration state only

const Step = ({ step }) => {
const { id, title, options, parent_step } = step;
const [configuration, setConfiguration] = useContext(ConfiguratorContext);

const handleChange = (e) => {
const value = e.target.value;
// Store value of current step to later update configuration in state
const configurationUpdate = { [id]: value };
if (options && options.length > 0) {
options.forEach((option) => {
// Get current selected option and check whether it has child steps
if (option.id === value && option.child_steps) {
option.child_steps.forEach((stepId) => {
// Prepare values of child steps so they can be stored in configuration state
const childStep = steps.find((step) => step.id === stepId);
if (childStep) {
configurationUpdate[stepId] = childStep.id;
}
});
}
});
}
setConfiguration((prevConfig) => ({
...prevConfig,
...configurationUpdate
}));
};

const getClassName = () => {
const classes = ["step"];
if (parent_step && !configuration[parent_step] && !configuration[id])
classes.push("d-none");
return classes.join(" ");
};

return (
<div className={getClassName()}>
<label>{title}</label>
<select className="step-dropdown" onChange={handleChange}>
<option value="">-- Select --</option>
{options.map((option) => (
<option key={option.id} value={option.id}>
{option.title}
</option>
))}
</select>
</div>
);
};

export default Step;

我已经研究了 3 天的解决方案,但未能找到解决方案。我觉得我的方法不对,所以我希望有人能给我一些建议或想法,告诉我如何以更聪明的方式解决这个问题。

我的方法:

  • 根据配置状态中的值显示(子)步骤
  • 创建一个单独的状态来存储根据其 id 折叠的字段
  • 加载state中的steps数据,存储每一步下的step collapse和configuration

我的代码沙盒:

https://codesandbox.io/embed/epic-almeida-04ykwe?fontsize=14&hidenavigation=1&theme=dark

最佳答案

您可以使用以下内容,

App.js

import steps from "./steps.js";
import Step from "./components/Step";

export default function App() {
return (
<div className="App">
<div className="steps">
{/* iterate through all root level steps (ignore steps with parent step) */}
{steps.filter(x => !x.parent_step).map((step) => (
<Step key={step.id} step={step} />
))}
</div>
</div>
);
}

Step.js

import { useMemo, useState } from "react";
import steps from "../steps";

const Step = ({ step }) => {
const { id, title, options, parent_step } = step;

const handleChange = (e) => {
const value = e.target.value;
setSelectedStep(value);
};

const getClassName = () => {
const classes = ["step"];
return classes.join(" ");
};
{/* state to save selected option */}
const [selectedStep, setSelectedStep] = useState("");
{/* Calculate the child steps from the selected step (from current steps options get the steps specified by child steps) */}
const childSteps = useMemo(() => step.options.find(y => y.id === selectedStep)?.child_steps?.map(x => steps.find(z => z.id === x)), [selectedStep, step.options]);

return (
<div className={getClassName()}>
<label>{title}</label>
<select className="step-dropdown" onChange={handleChange}>
<option value="">-- Select --</option>
{options.map((option) => (
<option key={option.id} value={option.id}>
{option.title}
</option>
))}
</select>
{/* Using recursion to iterate through child steps */}
{childSteps && childSteps.map((s, i) => <Step key={i} step={s} />)}
</div>
);
};

export default Step;

关于javascript - 如何管理带有父字段和子字段的表单的显示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73402886/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com