Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

yup validation on multiple values

Tags:

yup

formik

I want to validate my form using yup in formik. Suppose I have 4 fields A, B, C, D and they are all strings. How should I write the validation schema if I want to have at least one of the fields is not empty, then that's a valid form? Thanks in advance!

like image 557
bunny Avatar asked Sep 10 '19 03:09

bunny


3 Answers

When using Yup if all normal features fail you, you can use the .test feature, documented here - https://github.com/jquense/yup#mixedtestname-string-message-string--function-test-function-schema

mixed.test(name: string, message: string | function, test: function): Schema

Adds a test function to the validation chain. Tests are run after any object is cast. Many types have some tests built in, but you can create custom ones easily. In order to allow asynchronous custom validations all (or no) tests are run asynchronously. A consequence of this is that test execution order cannot be guaranteed.

For your implementation you will want to write a "test" for each of your 4 fields to make sure one of the 4 are not null.

field1: yup
    .string()
    .test(
      'oneOfRequired',
      'One of Field1, Field2, Field3 or Field4 must be entered',
      function(item) {
        return (this.parent.field1 || this.parent.field2 || this.parent.field3 || this.parent.field4)
      }
    ),
field2: yup
    .string()
    .test(
      'oneOfRequired',
      'One of Field1, Field2, Field3 or Field4 must be entered',
      function(item) {
        return (this.parent.field1 || this.parent.field2 || this.parent.field3 || this.parent.field4)
      }
    ),

etc...

Please note in this case I have not used an arrow function. This is because to use the 'this' context you must use this syntax, this is mentioned in the Yup documentation.

like image 131
Jamie Shepherd Avatar answered Sep 16 '22 11:09

Jamie Shepherd


There's another possibility if you don't want to add the validation to every field but rather have a "global" error handler for these things.

You'd do something like this:

const schema = yup.object().shape({
    field1: yup.string().required(),
    field2: yup.string().required(),
    field3: yup.string().required(),
    field4: yup.string().required(),
}).test('yourTestCondition', function (value) {
    // your global test code...
})

like image 28
Tomas Dohnal Avatar answered Sep 18 '22 11:09

Tomas Dohnal


There is a solution for what you're searching. Instead of writing a test for each of the elements, you could just write one for the parent. Simulating a Global error.

yup.object({
field1: yup.string(), 
field2: yup.string(),
field3: yup.string(),
field4: yup.string(),
})
.test('global-ok',
      'you do not fulfill the requirements',
      function (value) {
        return CONDITION OVER THE CHILDREN;
      })
      
      

For example, if you don't want to write the error for a series of required elements and just give one type of global error. You could:

    yup.object({
    username: yup.string().required(), 
    password: yup.string().required(),
    email: yup.string().required().test(verify_email),
    })
    .test('global-ok',
          'The data is not correct',
          function (value) {
            return username && password && email;
          })
          
like image 34
Nicolas Falconi Avatar answered Sep 17 '22 11:09

Nicolas Falconi