Yup conditional validation based on a a non field value
Asked Answered
A

3

11

I am trying to create a yup schema where based on a variables value the schema changes slightly. In my case depending on the value of prop myCondition I need to make a field as required. I would like to know if there is any better way I can achieve the same using Yup. Here's my current code structure that works:

// config.js
const COMMON_SCHEMA = {
  str1: yup
    .string()
    .nullable()
    .required('Please input str1'),
  str3: yup
    .string()
    .nullable()
};
const VALIDATION_SCHEMA_1 = yup.object().shape({
  ...COMMON_SCHEMA,
  str2: yup.string().nullable(),
});

const VALIDATION_SCHEMA_2 = yup.object().shape({
  ...COMMON_SCHEMA,
  str2: yup
    .string()
    .nullable()
    .required('Please input str2'),
});

const SCHEMAS = {
  VALIDATION_SCHEMA_1,
  VALIDATION_SCHEMA_2
}
export default SCHEMAS;

the following is how I conditionally choose different schemas:

// app.js
import SCHEMAS from './config';
...

<Formik
  validationSchema={
    this.props.myCondition === true
      ? SCHEMAS.VALIDATION_SCHEMA_1
      : SCHEMAS.VALIDATION_SCHEMA_2
  }
>
...
</Formik>

I feel like I can achieve whatever I am doing above in an easier way with yup. One of the approaches I tried was to pass in the prop myCondition into config file and work with it's value by using yup.when() but when only works if the value you want to use is also a part of the form so I couldn't achieve the same.

Adornment answered 6/4, 2020 at 16:20 Comment(0)
U
11

This can be achieved by the following way:

You can wrap your schema in a function and pass your conditional prop:

const wrapperSchema = (condition) => 
  Yup.object().shape({
    ...COMMON_SCHEMA,
    str2: yup.string()
     .when([], {
       is: () => condition === true,
       then: yup.string().nullable(),
       otherwise: yup.string().required('Please input str2'),
     }),
  });

Please note that first param of when is a required param, you can also pass e.g. ["title", "name"] where title and name can be your field values, and you can retrieve and use them in is callback, in the same order, if you have to.

Ultimogeniture answered 9/8, 2022 at 9:25 Comment(0)
E
1

You can conditionally add validation directly in the validationSchema, like this: https://mcmap.net/q/458701/-conditional-validation-with-yup-and-formik

Edited to add, you can include your value in the initial form, so that you can do the when check against that field. For example:

<Formik 
  initialValues={
    ...,
    str2
  }
  validationSchema={
    ...,
    str2: yup.object().when('str2', {
      is: str2 => condition check that returns boolean,
      then: Yup.string().nullable(),
      otherwise: Yup.string().nullable().required('Please input str2')
    })
}
>
...
</Formik>
Elodea answered 24/2, 2021 at 0:31 Comment(0)
H
0

I had a similar issue and solved it as an input to my validation schema in the following way (this is a generic example):

export validationSchemaExample = (condition: boolean) =>
  yup.object().shape({
    field: yup.string().when([], {
      is: () => condition,
      then: () => yup.string().required("This field is required")
    }),

And then I refer to it as follows:

    <Formik
      ...
      validationSchema={validationSchemaExample(condition)}
    >
Hircine answered 15/4 at 12:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.