1

I have a validation schema object:

SCHEMA = object().shape({
  ...
  someField: string().required(validation_keys.required),
  ...
});

I am using useFormik within my component:

const formik = useFormik({
  initialValues: values,
  onSubmit: ...,
  validationSchema: SCHEMA,
});

I was looking for a way to pass an argument to my SCHEMA, so as someField would be required just when the argument is true... I read about context, also tried to do it with when(), but none of these worked for me...

My goal is to validate someField base on a component prop, not other field from formik. Something similar to the example below:

validationSchema={yup.object().shape({
    someField: yup
      .string()
      .when("xxx", {
        is: true,
        then: yup.string().required("Required"),
        otherwise: yup.string(),

      })
  })
}

xxx is supposed to be passed to validation schema in my React component where useFormik is used

jake-ferguson
  • 315
  • 3
  • 11
  • 32

3 Answers3

0

You can do something like this.

    const validationSchema= Yup.object({
      custom_field: Yup.string().test(
        "match",
        "Custom validation enabled",
        function () {
          if (!shouldFormValidate) return true;
          return false;
        }
      )
    });

Here the working codesandbox.

Nik
  • 1,589
  • 2
  • 15
  • 23
  • can it be done without adding additional for field? – jake-ferguson Jan 14 '21 at 08:59
  • Yes. instead of additional field you can use your argument field. Can you create one sample code-snippet? – Nik Jan 14 '21 at 09:02
  • @jake-ferguson Check updated answer and code sandbox. Let me know if it answers your question. – Nik Jan 14 '21 at 10:05
  • This works, but there is a twist to it I need help with. I don't want to display an error message but only highlight the text field with the error. Excluding the text will not highlight the field with this snippet. Can you suggest any ways to help me achieve the desired result? – Anjayluh Aug 03 '21 at 08:45
  • @Anjayluh can you please add a new question with code snippet describing exact problem that you are facing it will help me understand. I'm asking for new question because if I edit the existing answer then it will be no longer relevant with the OP. I hope you won't mind adding a new question. – Nik Aug 04 '21 at 15:23
0

If you want to validate a field based on a React component prop you can use withMutation:

schema = object({
  ...,
  someField: string(),
  ...
});

if(validation_keys.required) {
  schema.fields.someField.withMutation(schema => {
    schema.required();
  });
}

Example

Edit adoring-yonath-t7kcc

Fraction
  • 11,668
  • 5
  • 28
  • 48
0

While I'm not sure you can achieve this solely in the schema that you pass to Formik, there is an options param that you could use in your Yup Schema.validate. From the Yup docs:

Schema.validate accepts and returns the following: Schema.validate(value: any, options?: object): Promise<InferType<Schema>, ValidationError>

In which options is:

interface Options {
  // when true, parsing is skipped an the input is validated "as-is"
  strict: boolean = false;
  // Throw on the first error or collect and return all
  abortEarly: boolean = true;
  // Remove unspecified keys from objects
  stripUnknown: boolean = false;
  // when `false` validations will be performed shallowly
  recursive: boolean = true;
  // External values that can be provided to validations and conditionals
  context?: object;
}

The last key, context, is going to help you out here. You can use it to pass values that later can be accessed during validation.

Example from the docs:

let schema = object({
  isBig: boolean(),
  count: number()
    .when('isBig', {
      is: true, // alternatively: (val) => val == true
      then: (schema) => schema.min(5),
      otherwise: (schema) => schema.min(0),
    })
    .when('$other', ([other], schema) =>
      other === 4 ? schema.max(6) : schema,
    ),
});

await schema.validate(value, { context: { other: 4 } });

This solution obviously means you'll have to manually call schema.validate and can't rely on Formik doing that for you, but there are ways to achieve that as well, so if you really need your additional params to be available during validation, you can technically do it.

tdy
  • 36,675
  • 19
  • 86
  • 83