0

I have a very simple problem in my react app. I wanted to submit only the date and is_delicious if the (toggle switch is_delicious) is off. However how will i validate if the (toggle switch is_delicious) is on and then all the 3 fields is required.

Check this codesandbox link

CLICK HERE

    return (
    <Formik
      initialValues={{
        is_delicious: false,
        date: "",
        food_name: ""
      }}
      validationSchema={foodSchema}
      onSubmit={values => {
        const formData = {
          is_delicious: values.is_delicious === true ? 1 : 0,
          food_name: values.food_name
        };
        console.log(formData);
      }}
    >
      {({
        values,
        touched,
        errors,
        handleChange,
        handleBlur,
        setFieldValue,
        handleSubmit
      }) => (
        <form onSubmit={handleSubmit}>
          <TextField
            name="date"
            variant="outlined"
            value={values.date}
            onChange={handleChange}
            onBlur={handleBlur}
            helperText={touched.date ? errors.date : ""}
            error={touched.date && Boolean(errors.date)}
            label="Date"
            type="date"
            InputLabelProps={{
              shrink: true
            }}
            fullWidth
          />
          <FormControlLabel
            name="is_delicious"
            variant="outlined"
            value={values.is_delicious}
            checked={values.is_delicious}
            onChange={handleChange}
            onClick={() => getFoodValue(values.is_delicious)}
            onBlur={handleBlur}
            control={<Switch color="primary" />}
            label="Is Delicious?"
            labelPlacement="end"
            style={{ display: "flex", justifyContent: "center" }}
          />

          {showFood ? (
            <TableContainer component={Paper}>
              <Table className={classes.table} aria-label="simple table">
                <TableHead>
                  <TableRow>
                    <TableCell>Dessert (100g serving)</TableCell>
                    <TableCell align="right">Calories</TableCell>
                    <TableCell align="right">Fat&nbsp;(g)</TableCell>
                    <TableCell align="right">Carbs&nbsp;(g)</TableCell>
                    <TableCell align="right">Protein&nbsp;(g)</TableCell>
                  </TableRow>
                </TableHead>
                <TableBody>
                  {rows.map(row => {
                    const isItemSelected = isSelected(row);
                    return (
                      <TableRow
                        key={row.name}
                        hover
                        onClick={event => selectFood(event, row)}
                        selected={isItemSelected}
                        value={values.food_name}
                      >
                        <TableCell component="th" scope="row">
                          {row.name}
                        </TableCell>
                        <TableCell align="right">{row.calories}</TableCell>
                        <TableCell align="right">{row.fat}</TableCell>
                        <TableCell align="right">{row.carbs}</TableCell>
                        <TableCell align="right">{row.protein}</TableCell>
                      </TableRow>
                    );
                  })}
                </TableBody>
              </Table>
            </TableContainer>
          ) : (
            ""
          )}
          <Button type="submit" color="primary" variant="contained">
            Submit
          </Button>
        </form>
      )}
    </Formik>
  );
Joseph
  • 7,042
  • 23
  • 83
  • 181

1 Answers1

1

You can make use of the Yup conditions as explained here - Conditional validation with Yup and Formik

Here is the solved codesandbox for your problem - https://codesandbox.io/s/highlightselect-rows-react-material-j03zv?file=/demo.js

The validation scheme change which was required was to remove is_delicious: yup.string().required("Select"), from the validationScheme and add yup condition (both food_name and date needs to be validated only if is_delicious is true.) as below -

let foodSchema = yup.object().shape({
  food_name: yup.string().when("is_delicious", {
    is: true,
    then: yup.string().required("Select food")
  }),
  date: yup.string().when("is_delicious", {
    is: true,
    then: yup.string().required("Select Date")
  })
});

Note: I had to change the onClick of FoodTable to ensure food_name field is set properly.

onClick={event => {
   setFieldValue("food_name", row.name);
   selectFood(event, row);
}}

Hope this helps.

Update: Handled showing validation error message for selection of food_name by adding below code

<TableContainer
    className={
      touched.food_name && errors.food_name && classes.tableError
    }
    component={Paper}
>{...}</TableContainer>
  • Great. So i can i get the display the error message for the `food_name`. I just want it to be encircle or box just like the TextFields of the date. Thank you – Joseph Jul 07 '20 at 12:58
  • You can do that by checking `touched.food_name && errors.food_name` and assign a className to tableContainer accordingly. I have updated the code to showcase the same. – Arpitha Chandrashekara Jul 07 '20 at 13:24