react-hook-form: How to validate when either of two fileds are required

Viewed 3428

I have two fields itemlist and itemlistUpload

I am using react-hook-forms. I want the user to provide either one of the them. And one of them is required

How can i do the validation

import { useForm, Controller } from "react-hook-form";
import {
  Col,
  Row,
  Form,
  FormGroup,
  InputGroup,
  Input,
  Container
} from "reactstrap";

export default function App() {
  const onSubmit = (data) => {
    console.log(data);
  };

  const { control, handleSubmit } = useForm();

  return (
    <Container>
      <Form onSubmit={handleSubmit(onSubmit)}>
        <Row className="m-3">
          <Col>
            <Controller
              name="itemlist"
              control={control}
              render={({ field: { ref, ...field } }) => (
                <Input
                  {...field}
                  type="textarea"
                  rows={10}
                  placeholder="itemlist"
                  required
                  innerRef={ref}
                />
              )}
            />
          </Col>
        </Row>
        <Row className="m-3">
          <Col>
            <FormGroup row className="mr-md-1">
              <InputGroup className="mb-3">
                <Controller
                  name="itemlist2"
                  control={control}
                  render={({ field: { ref, ...field } }) => (
                    <Input
                      {...field}
                      type="file"
                      required
                      innerRef={ref}
                    />
                  )}
                />
              </InputGroup>
            </FormGroup>
          </Col>
        </Row>
      </Form>
    </Container>
  );
}

Here is the codesandbox https://codesandbox.io/s/bitter-grass-erz7t

1 Answers

Remove the 'required' attribute from both inputs and validate the fields manually by using setError and clearErrors functions from useForm. (https://react-hook-form.com/api/useform/seterror, https://react-hook-form.com/api/useform/clearerrors)

Check if one of the fields have been filled out in when the form has been submitted, if not, set a new error and don't log the data. Then add logic to the inputs' onChange functions to clearErrors once data has been entered.

import "./styles.css";
import { useForm, Controller } from "react-hook-form";
import {
  Col,
  Row,
  Form,
  FormGroup,
  InputGroup,
  Input,
  Container
} from "reactstrap";

export default function App() {
  const onSubmit = (data) => {
    if (!data.itemlist && !data.itemlist2) {
      setError("neitherItemlist", {
        type: "manual",
        message: "You must fill out either itemlist or itemlist1"
      });
      return;
    }
    console.log(data);
  };

  const {
    control,
    handleSubmit,
    setError,
    formState: { errors },
    clearErrors
  } = useForm();

  return (
    <Container>
      <Form onSubmit={handleSubmit(onSubmit)}>
        <Row className="m-3">
          <Col>
            <Controller
              name="itemlist"
              control={control}
              render={({ field: { ref, ...field } }) => (
                <Input
                  {...field}
                  type="textarea"
                  rows={10}
                  placeholder="itemlist"
                  innerRef={ref}
                  onChange={(e) => {
                    field.onChange(e);
                    clearErrors("neitherItemlist");
                  }}
                />
              )}
            />
          </Col>
        </Row>
        <Row className="m-3">
          <Col>
            <FormGroup row className="mr-md-1">
              <InputGroup className="mb-3">
                <Controller
                  name="itemlist2"
                  control={control}
                  render={({ field: { ref, ...field } }) => (
                    <Input
                      {...field}
                      type="file"
                      innerRef={ref}
                      onChange={(e) => {
                        field.onChange(e);
                        clearErrors("neitherItemlist");
                      }}
                    />
                  )}
                />
              </InputGroup>
            </FormGroup>
          </Col>
        </Row>
        {errors.neitherItemlist && (
          <p style={{ color: "red" }}>{errors.neitherItemlist.message}</p>
        )}
        <input type="submit" />
      </Form>
    </Container>
  );
}

https://codesandbox.io/s/confident-brook-14zwj?file=/src/App.js:0-2208

Related