Skip to content
Advertisement

Validation in Yup React based on the value of checkbox

I am building a form in React using React-form-hook and validation using yup.

I am using a watch() to check if the checkbox is clicked or not and if it is clicked it will display another input field in the form which was not visible before.

Even when I haven’t clicked the checkbox which means that refer input field is not visible or rendered, it still does not perform the handlesubmit.

I can’t think of a way to get around this.

   <div className="form-check">
      <input type="checkbox" id="askRefer" {...register("askRefer")} />
      <label className="form-check-label" htmlFor="askRefer">
        Refered ?
      </label>
   </div>

  {referedStatus && (
      <div className="form-group">
        <label htmlFor="referedNumber">Refereed Number</label>
        <input
          type="text"
          className="form-control"
          placeholder="refer number"
          {...register("refer")}
        />
        {errors.refer && (
          <p className="error-message">{errors.refer.message}</p>
        )}
      </div>
    )}

Validation code in yup.

const valSchema = yup.object().shape({
    email: yup.string()
          .required("email is required")
          .email("only accepts an email"),
    password: yup.string().required("password cannot be empty"),
    confirmPassword: yup.string()
           .required("confirmation of password is important")
           .oneOf([yup.ref("password"), null], "password doesn't match"),
    refer:yup.number()
             .required("please input refer number")
             .positive("entry should be greater than 0")
             .integer("input integer value"))
   });

Reat-hook-form:

 const {register, handleSubmit, watch, formState: { errors }} = useForm({
                                                        resolver: yupResolver(valSchema),
                                                        mode: "onTouched",
                                                        });
let referedStatus= watch("askRefer", false);

If it helps, the complete code is here:

import React from "react";
import { useForm } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";
import * as yup from "yup";

function Rform() {


  const valSchema = yup.object().shape({
    email: yup
      .string()
      .required("email is required")
      .email("only accepts an email"),
    password: yup.string().required("password cannot be empty"),
    confirmPassword: yup
      .string()
      .required("confirmation of password is important")
      .oneOf([yup.ref("password"), null], "password doesn't match"),
    refer:(yup
      .number()
      .required("please input refer number")
      .positive("entry should be greater than 0")
      .integer("input integer value"))
  });

  console.log(valSchema)

  const {
    register,
    handleSubmit,
    watch,
    formState: { errors },
  } = useForm({
    resolver: yupResolver(valSchema),
    mode: "onTouched",
  });

let referedStatus= watch("askRefer", false);

  const onSubmit = (formData) => {
    let url = "http://localhost:4000/things/register";
    fetch(url, {
      method: "POST",
      headers: {'Content-Type': 'application/json'},
      body: JSON.stringify(formData)
    })
      .then((response) => response.json())
      .then((result) => console.log(result));
  };
  console.log(referedStatus);

  return (
    <div className="container" onSubmit={handleSubmit(onSubmit)}>
      <form>
        <div className="form-group">
          <label>Email address</label>
          <input
            className="form-control"
            aria-describedby="emailHelp"
            placeholder="Enter email"
            {...register("email")}
          />
          <small className="form-text text-muted">
                We don't share the credential.
          </small>
          {errors.email && (
            <p className="error-message">{errors.email.message}</p>
          )}
        </div>
        <div className="form-group">
          <label>Password</label>
          <input
            type="password"
            className="form-control"
            placeholder="Password"
            {...register("password")}
          />
          {errors.password && (
            <p className="error-message">{errors.password.message}</p>
          )}
        </div>

        <div className="form-group">
          <label>Password</label>
          <input
            type="password"
            className="form-control"
            placeholder="Password"
            {...register("confirmPassword")}
          />
          {errors.confirmPassword && (
            <p className="error-message">{errors.confirmPassword.message}</p>
          )}
        </div>

        <div className="form-check">
          <input type="checkbox" id="askRefer" {...register("askRefer")} />
          <label className="form-check-label" htmlFor="askRefer">
            Refered ?
          </label>
        </div>

        {referedStatus && (
          <div className="form-group">
            <label htmlFor="referedNumber">Refereed Number</label>
            <input
              type="text"
              className="form-control"
              placeholder="refer number"
              {...register("refer")}
            />
            {errors.refer && (
              <p className="error-message">{errors.refer.message}</p>
            )}
          </div>
        )}

        <button type="submit" className="btn btn-primary">
          Submit
        </button>
      </form>
    </div>
  );
}

export default Rform;

This is what form looks like in the browser.

enter image description here

Advertisement

Answer

This is because the optional field “refer” (as long as “askRefer” is false) is required in your yup schema. You have to add your “askRefer” checkbox to the yup schema and then you can check via the when method, to set validation for “refer” if “askRefer” is true.

const valSchema = yup.object().shape({
  email: yup
    .string()
    .required("email is required")
    .email("only accepts an email"),
  password: yup.string().required("password cannot be empty"),
  confirmPassword: yup
    .string()
    .required("confirmation of password is important")
    .oneOf([yup.ref("password"), null], "password doesn't match"),
  askRefer: yup.boolean(),
  refer: yup.number().when("askRefer", {
    is: true,
    then: yup
      .number()
      .required("please input refer number")
      .positive("entry should be greater than 0")
      .integer("input integer value")
  })
});

Edit React Hook Form - Basic (forked)

Advertisement