0

So while learning, forms i found this package - yup for validating. But i am getting a problem

So i will explain the problem statement and what i have tried so far.

So the use case is i have a select field, which has two options, Resident and Non-Resident, so based on the selection i have different fields which i render

  • Resident : first_name, last_name
  • Non-Resident: passport_number, country, state

So here what i thought of splitting the schema and based on the selection i want to add the additional fields schema for the validation.

const required = () => "Field is required";

const resident_schema = object({
  first_name: string().required(required).nullable(),
  last_name: string().required(required).nullable(),
});

const non_resident_schema = object({
  passport_number: string().required(required).nullable(),
  country: object().required(required).nullable(),
  state: object().required(required).nullable(),
});

const schemaBasedCitizen = {
  RESIDENT: resident_schema,
  NON-RESIDENT: non_resident_schema,
};

export const validationSchema = object().shape({
  citizen: object().required(required).nullable(),
  { ...object().when("citizen", {
    is: (value) => !!schemaBasedCitizen[value.toUpperCase()],
    then: (value) => schemaBasedCitizen[value.toUpperCase()],
  }) },
});

And my html consist of

<select>
 <option disabled selected value> -- select an option -- </option>
 <option value='resident'>Resident</option>
 <option value='non-resident'>Non-Resident</option>
</select>

I am not able to spread, since key requires, So is there a way to achieve this.

Update

Schema when value is resident in select field

export const validationSchema = object().shape({
      citizen: object().required(required).nullable(),
      first_name: string().required(required).nullable(),
      last_name: string().required(required).nullable(),
    });

Schema when value is non-resident in select field

export const validationSchema = object().shape({
      citizen: object().required(required).nullable(),
      passport_number: string().required(required).nullable(),
      country: object().required(required).nullable(),
      state: object().required(required).nullable(),
    });

Basically the validation is dynamic based on the value on citizen select field.

dev
  • 814
  • 10
  • 27

1 Answers1

2

yup has this thing that it can only reference sibling fields (or context) using when.

Your citizen field is NOT a sibling of the rest of the object and can't be used to conditionally change the object schema, it's a child of the object, so you can't reference it as a sibling field via when.

One way to accomplish what you want could be to use a lazy schema:

import { lazy } from 'yup';

const residentSchema = ...
const nonResidentSchema = ...

export const validationSchema = lazy(({citizen}) => citizen === 'resident' ? residentSchema : nonResidentSchema);
Adam Jenkins
  • 51,445
  • 11
  • 72
  • 100
  • Okay, but one doubt, tried this but every time its overwriting. So the use case i selected resident, now i clicked on the first name field and didn't entered anything and clicked on last name field, now the error message shows, but when i click on the last name field the first name error is not persisting its overwriting. How can i solve this one. So at a time only one error message shows even though two fields have empty value – dev Sep 30 '20 at 13:35
  • @JohnThomas - that sounds like a completely different issue (deserving of a different question). It depends on the framework you're using to manage your form data/display your error messages. – Adam Jenkins Sep 30 '20 at 13:37
  • @ Adam Sure i will add a codesandbox for the issue to reproduce and will add here. Kindly guide me on the same. – dev Sep 30 '20 at 13:38
  • @ Adam this is the codesandbox, where i tried, but i think some re rendering is happening. I am not understanding where the issue is occurring. Let me know what i am doing wrong over here, and how can i solve the issue. Values also getting reset https://codesandbox.io/s/dawn-dust-lnyqu – dev Sep 30 '20 at 14:27
  • @JohnThomas - please open another question. – Adam Jenkins Sep 30 '20 at 14:29
  • @ Adam sure. will open and share here – dev Sep 30 '20 at 14:30
  • @ Adam, can you check this one https://stackoverflow.com/questions/64139855/form-validation-with-conditional-fields-using-yup – dev Sep 30 '20 at 14:34
  • @ Adam where you able to run it – dev Sep 30 '20 at 15:53