fabian-hiller / valibot

The modular and type safe schema library for validating structural data 🤖
https://valibot.dev
MIT License
5.6k stars 169 forks source link

Conditionally validate using pipes #645

Closed ttonyh closed 2 weeks ago

ttonyh commented 3 weeks ago

Now that the new version is released, what's the proper way to handle conditional validation? What's the best way to handle it based on parameters external to the schema (ie. not the typical scenario of "password" / "verify password")?

fabian-hiller commented 3 weeks ago

The official recommendation is to use the check action together with the forward method. This week or next I will also work on a partialCheck and refine action (issue #597) that will help cover more advanced cases.

import * as v from 'valibot';

const RegisterSchema = v.pipe(
  v.object({
    email: v.pipe(
      v.string(),
      v.nonEmpty('Please enter your email.'),
      v.email('The email address is badly formatted.')
    ),
    password1: v.pipe(
      v.string(),
      v.nonEmpty('Please enter your password.'),
      v.minLength(8, 'Your password must have 8 characters or more.')
    ),
    password2: v.string(),
  }),
  v.forward(
    v.check(
      (input) => input.password1 === input.password2,
      'The two passwords do not match.'
    ),
    ['password2']
  )
);
fabian-hiller commented 2 weeks ago

Update: Previously, check was not executed if the email field was untyped. This problem can now be solved with our new partialCheck action.

import * as v from 'valibot';

const RegisterSchema = v.pipe(
  v.object({
    email: v.pipe(
      v.string(),
      v.nonEmpty('Please enter your email.'),
      v.email('The email address is badly formatted.'),
    ),
    password1: v.pipe(
      v.string(),
      v.nonEmpty('Please enter your password.'),
      v.minLength(8, 'Your password must have 8 characters or more.'),
    ),
    password2: v.string(),
  }),
  v.forward(
    v.partialCheck(
      [['password1'], ['password2']],
      (input) => input.password1 === input.password2,
      'The two passwords do not match.',
    ),
    ['password2'],
  ),
);