Yup: How to validate field only when it exists?
Asked Answered
P

7

12

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.

Plangent answered 7/1, 2021 at 13:48 Comment(0)
B
8

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.

Benediction answered 7/1, 2021 at 14:43 Comment(9)
I had tried that way before, but not work. I think this is work for same step instead of step to step. because isEmail is from step 1 and use it on step 2. @Benediction @Dharman Do you have further solution on this stuff? Thanks.Plangent
Are your forms different for both steps? or is it just one single form split in steps?Benediction
form different for both stepsPlangent
Oh ok. You can set the initialSchema based on step 1 form values. Since you know whether to show email field or not, you can modify the initialSchema for second step form and reinitialize the form based on same value. Can you provide the code snippet of your code?Benediction
Pls check out code snippet. I dunno how to set initial Schema base on step 1 and use it. Do you have any some example?Plangent
Please check the updated answer. I've modified the codesandbox and added working solution.Benediction
I am still getting validation message when using this with a date field, setting it to yup.date() instead of yup.string. Does one need to do something else for dates?Lapp
@Lapp can you please add a snippet to help me understand the problem?Benediction
can you help to answer this #75125186Bibliographer
S
7

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()
    })
})
Segmental answered 12/4, 2022 at 20:28 Comment(3)
Thank you! This works for me. I like this solution is more simpe.Toluol
This does not work for me.Internist
can you help to answer this #75125186Bibliographer
T
2

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']]);
Television answered 5/9, 2022 at 21:6 Comment(0)
M
0

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;
        })
Mobility answered 4/3, 2021 at 14:45 Comment(0)
T
0

I know this is late but maybe someone is going to need this answer .I've tried all the above answers and nothing worked, this the solution that i tried and it works perfectly.

In my case i had a condition based on it i display or hide the textfield, so this the solution :

const validationSchema = Yup.object().shape({
    yourFieldHere: Yup.number().when(["service"], (service, schema) => {
      return (your condition here)
        ? schema.typeError("your msg here ").required("your msg here ")
        : schema.nullable();
    }),
  });
Thermosiphon answered 30/11, 2023 at 11:46 Comment(0)
S
0

Yes, it is possible to validate a field only when it exists No, above solutions worked for me, so I wrote a custom test function, might help :)

authorityUrl: yup.string().trim().test('is-valid-url', 'Invalid Url', function (value) {
     if (value && value.length > 0) {
          return /^(https?:\/\/)?([A-Za-z0-9]+\.[A-Za-z0-9]+)/i.test(value);
     }
     return true; // Skip validation if field is empty
}),
Seville answered 2/4 at 8:12 Comment(0)
A
-1

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

Adapt answered 7/1, 2021 at 13:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.