Yup: How to validate field only when it exists?

Viewed 12648

Is it possible to validate a field only when it exists?

I'm going to create an application. A field(email) may / may not display on step 2, it depends on the step 1's selected option. The problem is that I can't put email: Yup.string().Required(), it causes that the validation run all the time even the field is not displayed.

5 Answers

You can set a additional boolean key where value is default false. Change it to true when you modify the value in step 1. And then if the value is true for that key then apply the validation.

Something like this.


    const initialSchema= {
      name: '',
      isEmail: false, // change this when you want to add validation
      email: '',
      phone: '',
    };
    
    const validationSchema = Yup.object().shape({
      name: Yup.string()
        .required('Enter Name')
      isEmail: Yup.boolean(),
      email: Yup.string().when('isEmail', {
         is: true,
         then: Yup.string()
         .required('Enter Email ID'),
         otherwise: Yup.string(),
      }),
      phone: Yup.string()
        .required('Enter Mobile No'),
    });

Here is the documentation reference for same.

Update:

Here is the working codesandbox. I've added checkbox with display:none;, and added the default state values in data context.

I saw another related answer here, maybe this is a valid solution too?

https://github.com/jquense/yup/issues/1114

Copying code from there:

const schema = yup.object({
    phone: yup.string().when('$exist', {
        is: exist => exist,
        then: yup.string().required(),
        otherwise: yup.string()
    })
})

You need to handle with manually, not with required. Just you need to keep a state of the each field. And check it if its value is present then you need to show it. Some like this

const [email, setEmail]= useState(null);

const onChange=(e)=>{
setEmail(e.target.value)
}

return (


<input type="text" onChange={onChnage}/>
)

And pass this email to your parent where you checking for validation. If there is any thin in email then show it do other validation. Or if it is empty or Null then don't show it.

Thanks

I modify the schema on the fly with a transform

  const updateUserValidator = yup.object().shape({
        email: yup.string(),
        updateBy: yup.string()
    }).transform(function (current, original) {
        this.fields.email = original?.email?.length === undefined ? yup().string().email() : yup().string().email().required()
        return current;
        })

You can use Cyclic Dependency for make this.

Example:

const YOUR_SCHEMA_NAME = yup.object().shape({
    email: yup.string().when('email', {
        is: (exists) => !!exists,
        then: yup.string().email(),
        otherwise: yup.string(),
    }),
}, [['email', 'email']]);
Related