Laurence Fass
Laurence Fass

Reputation: 1942

react hook form: how can i validate a group of radio buttons or checkboxes to ensure at least one is selected

I have a group of checkboxes and a group if radios and I want to validate with react hook form to ensure that an error message is generated if none have been selected on submit.

I have tried experimenting with the form builder on their website but I cant work out how to validate a group of items as a single unit of validation.

<div>
  <span>Option A <input type="checkbox" value="A" /></span>
  <span>Option B <input type="checkbox" value="B" /></span>
  <span>Option C <input type="checkbox" value="C" /></span>
</div>
<...output a validation error if one or more checkboxes hasnt been checked within the group>
<div>
  <span>Option A <input type="radio" value="A" /></span>
  <span>Option B <input type="radio" value="B" /></span>
  <span>Option C <input type="radio" value="C" /></span>
</div>
<...output a validation error if one or more radios hasnt been checked within the group>

Is this possible and is there a correct way to do it?

Thank you for your time and attention.

Upvotes: 4

Views: 15178

Answers (3)

Mahadev Mandal
Mahadev Mandal

Reputation: 154

Check out detailed guide

It's possible to validate a group of checkboxes and a group of radio buttons as a single unit using React Hook Form. You can use React Hook Form's register function to handle validation without needing external validation libraries like Yup.

Here's a simple example:

import { useForm } from "react-hook-form";
import { useState } from "react";

export default function App() {
  const [submitted, setSubmitted] = useState(false);
  const {
    register,
    handleSubmit,
    formState: { errors },
    reset,
  } = useForm({
    defaultValues: {
      checkbox: [],
      radio: "",
    },
  });

  const submit = (data) => {
    setSubmitted(true);
    console.log("Submitted data:", data);
    reset();
  };

  return (
    <div className="App">
      <div className="container">
        {/* Checkbox group */}
        <div className="form-group">
          <span>
            Checkbox A
            <input
              type="checkbox"
              value="A"
              {...register("checkbox", {
                required: "Select at least one checkbox",
              })}
            />
          </span>
          <span>
            Checkbox B
            <input type="checkbox" value="B" {...register("checkbox")} />
          </span>
          <span>
            Checkbox C
            <input type="checkbox" value="C" {...register("checkbox")} />
          </span>
        </div>
        {/* Display error messages */}
        {errors.checkbox && <p className="error">{errors.checkbox.message}</p>}
      </div>
      <div className="container">
        {/* Radio group */}
        <div className="form-group">
          <span>
            Radio A
            <input
              type="radio"
              value="A"
              {...register("radio", { required: "Select at least one radio" })}
            />
          </span>
          <span>
            Radio B
            <input type="radio" value="B" {...register("radio")} />
          </span>
          <span>
            Radio C
            <input type="radio" value="C" {...register("radio")} />
          </span>
        </div>
        {/* Display error messages */}
        {errors.radio && <p className="error">{errors.radio.message}</p>}
      </div>
      {/* Submit button */}
      <button onClick={handleSubmit(submit)}>Submit</button>
      {submitted && <p>Form submitted.</p>}
    </div>
  );
}

See a working codesandbox.

Upvotes: -1

lbsn
lbsn

Reputation: 2412

You added the react-hook-form tag to your question but there is nothing in your code related to it. If indeed you're using React Hook Form a way to accomplish what you want is using schema validation through yup:

const schema = yup.object().shape({
  checkbox: yup.array().min(1),
  radio: yup.string().required(),
});

export default function App() {
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm({
    resolver: yupResolver(schema),
  });
  const onSubmit = (data) => {
    alert(JSON.stringify(data));
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <span>
        Checkbox 1
        <input type="checkbox" {...register('checkbox')} value="A" />
      </span>
      <span>
        Checkbox 1
        <input type="checkbox" {...register('checkbox')} value="B" />
      </span>
      <span>
        Checkbox 3
        <input type="checkbox" {...register('checkbox')} value="C" />
      </span>
      <p style={{ color: 'red' }}>
        {errors.checkbox && 'At least one checkobox must be selected'}
      </p>
      <span>
        <label>Radio 1</label>
        <input type="radio" {...register('radio')} value="A" />
      </span>
      <span>
        <label>Radio 2</label>
        <input type="radio" {...register('radio')} value="B" />
      </span>
      <span>
        <label>Radio 3</label>
        <input type="radio" {...register('radio')} value="C" />
      </span>
      <p style={{ color: 'red' }}>{errors.radio && 'Radio is required'}</p>
      <input type="submit" />
    </form>
  );
}

See a working stackblitz.

Note that as radio button options are exclusive (only one can be selected) you're just sayng that the field is required.

Upvotes: 7

Pierre Lejay
Pierre Lejay

Reputation: 66

Check out this guide and the documentation for radio buttons

In short, giving the same name attribute to your radio buttons ensures that only one of them can be selected at a time. Adding an onChange function linked to a useState within your component allows you to track the selected value and react if none has been selected.

The resulting code should be something like this:

const YourComponent = () => {
  const [myValue, setMyValue] = useState(null);

  const onValueChange = e => {
    setMyValue(e.target.value);
  };
  return (
    <div>
      <div onChange={onValueChange}>
        <span>
          Option A <input type="checkbox" value="A" name="myValue" />
        </span>
        <span>
          Option B <input type="checkbox" value="B" name="myValue" />
        </span>
        <span>
          Option C <input type="checkbox" value="C" name="myValue" />
        </span>
      </div>
      {!myValue && <span>Please select a value</span>}
    </div>
  );
};

Upvotes: 0

Related Questions