使用 Material UI 和 Formik 处理多个复选框
Handling Multiple Checkboxes with Material UI and Formik
我有一个带有复选框组的表单,其中包含 4 个复选框。我需要在提交要通过 Formik 处理的按钮时将值传递给我的 api。
点击特定复选框有几个条件:
- 如果选中高度,则还应选中其余部分
- 如果勾选了宽度,除了高度之外都应该勾选
- 如果勾选了Length,那么Nos和Length都应该勾选
编号可以勾选或不勾选
目前,我正在为所有复选框声明单独的状态,并为上述每个条件声明单独的函数。
是否有任何其他方法可以将复选框中的值绑定到 Formik 并传递给 api
国家和个人职能:
const [nos, setNos] = useState(false);
const [length, setLength] = useState(false);
const [breadth, setBreadth] = useState(false);
const [height, setHeight] = useState(false);
const handleHeight = e => {
setNos(!nos);
setLength(!length);
setBreadth(!breadth);
setHeight(!height);
};
const handleBreadth = e => {
setNos(!nos);
setLength(!length);
setBreadth(!breadth);
};
const handleLength = e => {
setNos(!nos);
setLength(!length);
};
const handleNos = e =>{
setNos(!nos);
};
使用 Formik 的表格:
const formik = useFormik({
initialValues,
validationSchema,
onSubmit: async (values) => {
alert(JSON.stringify(values, null, 2));
},
});
return (
<>
<form
onKeyDown={onKeyDown}
id="newJobDetails"
name="newJobDetails"
onSubmit={formik.handleSubmit}
className={CommonClasses.formPartStyling}
style={{
height: SetFormSize(
isAdd ? "Add" : textFieldDisable ? "Info" : "Edit",
1
),
marginTop: marginTop || "none",
}}
>
<div
className={CommonClasses.headingTextOfForms}
style={{ marginLeft: "4%", marginTop: "2%" }}
>
Add Jobs
</div>
<Divider
style={{
marginTop: "1%",
marginBottom: "3%",
color: "white",
}}
></Divider>
<div
style={{
marginLeft: "4%",
marginTop: "2%",
}}
>
<Grid container>
<Grid item xs={6}>
<LabelStyling>Job Name</LabelStyling>
<TextField
id="jobName"
name="jobName"
variant="outlined"
placeholder="Enter Job Name"
value={formik.values.jobName}
onChange={formik.handleChange}
size="small"
style={{
width: FORM_PART_VARS.INPUT_BOX_WIDTH,
}}
/>
</Grid>
<Grid item xs={6}>
<LabelStyling>Stage</LabelStyling>
<DropDown
id="stage"
width={FORM_PART_VARS.INPUT_BOX_WIDTH}
value={formik.values.stage}
onChange={formik.handleChange}
error={formik.touched.stage && Boolean(formik.errors.stage)}
helperText={formik.touched.stage && formik.errors.stage}
mapFile={Stage}
placeholder="Select Stage"
/>
</Grid>
</Grid>
</div>
<div
style={{
marginLeft: "4%",
marginTop: "2%",
}}
>
<Grid container>
<Grid item xs={6}>
<LabelStyling>Measurement</LabelStyling>
<TextField
id="measurement"
name="measurement"
variant="outlined"
placeholder="Enter Measurement"
value={formik.values.measurement}
onChange={formik.handleChange}
size="small"
style={{
width: FORM_PART_VARS.INPUT_BOX_WIDTH,
}}
/>
</Grid>
<Grid item xs={6}>
<LabelStyling>Measurement Unit</LabelStyling>
<DropDown
id="measurement_unit"
width={FORM_PART_VARS.INPUT_BOX_WIDTH}
value={formik.values.measurement_unit}
onChange={formik.handleChange}
error={
formik.touched.measurement_unit &&
Boolean(formik.errors.measurement_unit)
}
helperText={
formik.touched.measurement_unit &&
formik.errors.measurement_unit
}
mapFile={MeasurementUnit}
placeholder="Select Unit"
/>
</Grid>
</Grid>
</div>
<div
style={{
marginLeft: "4%",
marginTop: "2%",
}}
>
<Grid container>
<Grid item xs={6}>
<LabelStyling>Rate</LabelStyling>
<TextField
name="jobRate"
id="jobRate"
variant="outlined"
placeholder="Enter Rate"
value={formik.values.jobRate}
onChange={formik.handleChange}
size="small"
style={{
width: FORM_PART_VARS.INPUT_BOX_WIDTH,
}}
/>
</Grid>
<Grid item xs={6}>
<LabelStyling>Service Rate</LabelStyling>
<TextField
name="serviceRate"
id="serviceRate"
variant="outlined"
placeholder="Enter Service Rate"
value={formik.values.serviceRate}
onChange={formik.handleChange}
size="small"
style={{
width: FORM_PART_VARS.INPUT_BOX_WIDTH,
}}
/>
</Grid>
</Grid>
</div>
<div
style={{
marginLeft: "4%",
marginTop: "4%",
}}
>
<LabelStyling>Select Measurement(s)</LabelStyling>
<FormGroup row>
<FormControlLabel control={<CheckBox checked={nos} onChange={handleNos} name="Nos" id="1"/>} label="Nos" />
<FormControlLabel control={<CheckBox checked={length} onChange={handleLength} name="Length" id="2"/>} label="Length" style={{marginLeft: "15px"}}/>
<FormControlLabel control={<CheckBox checked={breadth} onChange={handleBreadth} name="Breadth" id="3"/>} label="Breadth" style={{marginLeft: "15px"}}/>
<FormControlLabel control={<CheckBox checked={height} onChange={handleHeight} name="Height" id="4"/>} label="Height" style={{marginLeft: "15px"}}/>
</FormGroup>
</div>
<div
style={{
marginLeft: "4%",
marginTop: "4%",
}}
>
<LabelStyling>Select Job Type</LabelStyling>
<FormGroup row>
<FormControlLabel control={<CheckBox name="jobType" value="Residential"/>} label="Residential"/>
<FormControlLabel control={<CheckBox name="jobType" value="Commercial"/>} label="Commercial"/>
<FormControlLabel control={<CheckBox name="jobType" value="Infrastructure"/>} label="Infrastructure"/>
</FormGroup>
</div>
</form>
</>
);
要组合多个状态和多个处理程序,请尝试这样的操作:
const [state, setState] = useState({
nos: false,
length: false,
breadth: false,
height: false
});
const handleCheckBox = useCallback((checkbox) => () => setState(state => {
switch (checkbox) {
case 'nos': return {
...state,
nos: !state.nos,
};
case 'length': return {
...state,
nos: !state.nos,
length: !state.length,
};
case 'breadth': return {
...state,
nos: !state.nos,
length: !state.length,
breadth: !state.breadth,
};
case 'height': return {
...state,
nos: !state.nos,
length: !state.length,
breadth: !state.breadth,
height: !state.height,
};
default: {
console.warn('unknown checkbox', checkbox);
return state;
}
}
}), []);
<FormGroup row>
<FormControlLabel control={<CheckBox checked={state.nos} onChange={handleCheckBox('nos')} name={'Nos'} id={'1'}/>} label={'Nos'}/>
<FormControlLabel control={<CheckBox checked={state.length} onChange={handleCheckBox('length')} name={'Length'} id={'2'}/>} label={'Length'} style={{marginLeft: '15px'}}/>
<FormControlLabel control={<CheckBox checked={state.breadth} onChange={handleCheckBox('breadth')} name={'Breadth'} id={'3'}/>} label={'Breadth'} style={{marginLeft: '15px'}}/>
<FormControlLabel control={<CheckBox checked={state.height} onChange={handleCheckBox('height')} name={'Height'} id={'4'}/>} label={'Height'} style={{marginLeft: '15px'}}/>
</FormGroup>
使用 Formik 时,不需要维护额外的状态来捕获表单字段值,Formik 会处理这些。
在这种情况下,由于我们需要根据一个输入的变化以编程方式更改其他输入的值,我们可以使用 Formik 提供的 setFieldValue
道具。
我有一个带有复选框组的表单,其中包含 4 个复选框。我需要在提交要通过 Formik 处理的按钮时将值传递给我的 api。
点击特定复选框有几个条件:
- 如果选中高度,则还应选中其余部分
- 如果勾选了宽度,除了高度之外都应该勾选
- 如果勾选了Length,那么Nos和Length都应该勾选
编号可以勾选或不勾选
目前,我正在为所有复选框声明单独的状态,并为上述每个条件声明单独的函数。
是否有任何其他方法可以将复选框中的值绑定到 Formik 并传递给 api
国家和个人职能:
const [nos, setNos] = useState(false);
const [length, setLength] = useState(false);
const [breadth, setBreadth] = useState(false);
const [height, setHeight] = useState(false);
const handleHeight = e => {
setNos(!nos);
setLength(!length);
setBreadth(!breadth);
setHeight(!height);
};
const handleBreadth = e => {
setNos(!nos);
setLength(!length);
setBreadth(!breadth);
};
const handleLength = e => {
setNos(!nos);
setLength(!length);
};
const handleNos = e =>{
setNos(!nos);
};
使用 Formik 的表格:
const formik = useFormik({
initialValues,
validationSchema,
onSubmit: async (values) => {
alert(JSON.stringify(values, null, 2));
},
});
return (
<>
<form
onKeyDown={onKeyDown}
id="newJobDetails"
name="newJobDetails"
onSubmit={formik.handleSubmit}
className={CommonClasses.formPartStyling}
style={{
height: SetFormSize(
isAdd ? "Add" : textFieldDisable ? "Info" : "Edit",
1
),
marginTop: marginTop || "none",
}}
>
<div
className={CommonClasses.headingTextOfForms}
style={{ marginLeft: "4%", marginTop: "2%" }}
>
Add Jobs
</div>
<Divider
style={{
marginTop: "1%",
marginBottom: "3%",
color: "white",
}}
></Divider>
<div
style={{
marginLeft: "4%",
marginTop: "2%",
}}
>
<Grid container>
<Grid item xs={6}>
<LabelStyling>Job Name</LabelStyling>
<TextField
id="jobName"
name="jobName"
variant="outlined"
placeholder="Enter Job Name"
value={formik.values.jobName}
onChange={formik.handleChange}
size="small"
style={{
width: FORM_PART_VARS.INPUT_BOX_WIDTH,
}}
/>
</Grid>
<Grid item xs={6}>
<LabelStyling>Stage</LabelStyling>
<DropDown
id="stage"
width={FORM_PART_VARS.INPUT_BOX_WIDTH}
value={formik.values.stage}
onChange={formik.handleChange}
error={formik.touched.stage && Boolean(formik.errors.stage)}
helperText={formik.touched.stage && formik.errors.stage}
mapFile={Stage}
placeholder="Select Stage"
/>
</Grid>
</Grid>
</div>
<div
style={{
marginLeft: "4%",
marginTop: "2%",
}}
>
<Grid container>
<Grid item xs={6}>
<LabelStyling>Measurement</LabelStyling>
<TextField
id="measurement"
name="measurement"
variant="outlined"
placeholder="Enter Measurement"
value={formik.values.measurement}
onChange={formik.handleChange}
size="small"
style={{
width: FORM_PART_VARS.INPUT_BOX_WIDTH,
}}
/>
</Grid>
<Grid item xs={6}>
<LabelStyling>Measurement Unit</LabelStyling>
<DropDown
id="measurement_unit"
width={FORM_PART_VARS.INPUT_BOX_WIDTH}
value={formik.values.measurement_unit}
onChange={formik.handleChange}
error={
formik.touched.measurement_unit &&
Boolean(formik.errors.measurement_unit)
}
helperText={
formik.touched.measurement_unit &&
formik.errors.measurement_unit
}
mapFile={MeasurementUnit}
placeholder="Select Unit"
/>
</Grid>
</Grid>
</div>
<div
style={{
marginLeft: "4%",
marginTop: "2%",
}}
>
<Grid container>
<Grid item xs={6}>
<LabelStyling>Rate</LabelStyling>
<TextField
name="jobRate"
id="jobRate"
variant="outlined"
placeholder="Enter Rate"
value={formik.values.jobRate}
onChange={formik.handleChange}
size="small"
style={{
width: FORM_PART_VARS.INPUT_BOX_WIDTH,
}}
/>
</Grid>
<Grid item xs={6}>
<LabelStyling>Service Rate</LabelStyling>
<TextField
name="serviceRate"
id="serviceRate"
variant="outlined"
placeholder="Enter Service Rate"
value={formik.values.serviceRate}
onChange={formik.handleChange}
size="small"
style={{
width: FORM_PART_VARS.INPUT_BOX_WIDTH,
}}
/>
</Grid>
</Grid>
</div>
<div
style={{
marginLeft: "4%",
marginTop: "4%",
}}
>
<LabelStyling>Select Measurement(s)</LabelStyling>
<FormGroup row>
<FormControlLabel control={<CheckBox checked={nos} onChange={handleNos} name="Nos" id="1"/>} label="Nos" />
<FormControlLabel control={<CheckBox checked={length} onChange={handleLength} name="Length" id="2"/>} label="Length" style={{marginLeft: "15px"}}/>
<FormControlLabel control={<CheckBox checked={breadth} onChange={handleBreadth} name="Breadth" id="3"/>} label="Breadth" style={{marginLeft: "15px"}}/>
<FormControlLabel control={<CheckBox checked={height} onChange={handleHeight} name="Height" id="4"/>} label="Height" style={{marginLeft: "15px"}}/>
</FormGroup>
</div>
<div
style={{
marginLeft: "4%",
marginTop: "4%",
}}
>
<LabelStyling>Select Job Type</LabelStyling>
<FormGroup row>
<FormControlLabel control={<CheckBox name="jobType" value="Residential"/>} label="Residential"/>
<FormControlLabel control={<CheckBox name="jobType" value="Commercial"/>} label="Commercial"/>
<FormControlLabel control={<CheckBox name="jobType" value="Infrastructure"/>} label="Infrastructure"/>
</FormGroup>
</div>
</form>
</>
);
要组合多个状态和多个处理程序,请尝试这样的操作:
const [state, setState] = useState({
nos: false,
length: false,
breadth: false,
height: false
});
const handleCheckBox = useCallback((checkbox) => () => setState(state => {
switch (checkbox) {
case 'nos': return {
...state,
nos: !state.nos,
};
case 'length': return {
...state,
nos: !state.nos,
length: !state.length,
};
case 'breadth': return {
...state,
nos: !state.nos,
length: !state.length,
breadth: !state.breadth,
};
case 'height': return {
...state,
nos: !state.nos,
length: !state.length,
breadth: !state.breadth,
height: !state.height,
};
default: {
console.warn('unknown checkbox', checkbox);
return state;
}
}
}), []);
<FormGroup row>
<FormControlLabel control={<CheckBox checked={state.nos} onChange={handleCheckBox('nos')} name={'Nos'} id={'1'}/>} label={'Nos'}/>
<FormControlLabel control={<CheckBox checked={state.length} onChange={handleCheckBox('length')} name={'Length'} id={'2'}/>} label={'Length'} style={{marginLeft: '15px'}}/>
<FormControlLabel control={<CheckBox checked={state.breadth} onChange={handleCheckBox('breadth')} name={'Breadth'} id={'3'}/>} label={'Breadth'} style={{marginLeft: '15px'}}/>
<FormControlLabel control={<CheckBox checked={state.height} onChange={handleCheckBox('height')} name={'Height'} id={'4'}/>} label={'Height'} style={{marginLeft: '15px'}}/>
</FormGroup>
使用 Formik 时,不需要维护额外的状态来捕获表单字段值,Formik 会处理这些。
在这种情况下,由于我们需要根据一个输入的变化以编程方式更改其他输入的值,我们可以使用 Formik 提供的 setFieldValue
道具。