How to validate one field against another with Yup?

colin picture colin · Jun 21, 2019 · Viewed 10.4k times · Source

I'm setting up a form with two fields; start month and end month.

Start month and end month are just represented by integers (0-11) for the corresponding months. I need validation to ensure that end month comes after start month (ie the integer for end month is bigger).

I've looked at other similar issues from a few years back, but yup seems to have updated to render them useless. I've tried the below code with a few variations.

I am also having difficulty validating end month as a number (.number() - I'm assuming I have to maybe to do this within the test function.

let schema = yup.object().shape({
  startMonth: yup
    .number()
    .required()
    .positive()
    .integer(),
  endMonth: Yup.string().test(
  "End Month Validation",
  "error message",
  value => {
    return value > startMonth;
  }
)
.number()
.required()
.positive()
.integer(),
});

Errors: Line 102: 'startMonth' is not defined no-undef

Answer

Dacre Denny picture Dacre Denny · Jun 21, 2019

Another approach would be to make use of .ref() and .moreThan() to perform this validation logic.

Something like the following should achieve what you require:

let schema = Yup.object().shape({
  startMonth: Yup
    .number()
    .required()
    .positive()
    .integer(),
  endMonth: Yup.number() /* Remove .string() */
    .required()
    .positive()
    /* Reference startMonth field in validating endMonth value */
    .moreThan(Yup.ref('startMonth'), "End month must come after start month")
    .integer(),
});

schema.validate({ startMonth : 1, endMonth : 2 })  // Okay!
schema.validate({ startMonth : 11, endMonth : 2 }) // Throws exception

Hope that helps!