使用 Material UI 和 Formik 处理多个复选框

Handling Multiple Checkboxes with Material UI and Formik

我有一个带有复选框组的表单,其中包含 4 个复选框。我需要在提交要通过 Formik 处理的按钮时将值传递给我的 api。

点击特定复选框有几个条件:

  1. 如果选中高度,则还应选中其余部分
  2. 如果勾选了宽度,除了高度之外都应该勾选
  3. 如果勾选了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 道具。

Working Sandbox