Conditional validation
An alternative to requiredIf
rules is the Vine.union schema type that offers better type-safety at the cost of a verbose API.
Sometimes, you may want to mark a field as required based on some runtime conditions. For example, you want to keep the firstName
and lastName
fields optional but mark them as required when any one of them is present.
In the following example, we use the requiredIfExists
rule to mark the firstName
field as required when the lastName
field exists and vice-versa.
vine.object({
firstName: vine.string().optional().requiredIfExists('lastName'),
lastName: vine.string().optional().requiredIfExists('firstName'),
})
Alongside the requiredIfExists
rule, you can use one of the following rules to mark an optional field required based upon certain runtime conditions. These methods only exist on the optional
modifier.
requiredWhen
The requiredWhen
method is used to write comparison checks. The check could be an inline condition or a callback function (to express complex scenarios).
In the following example, we mark the volleyballLevel
field as required when the selected discipline
is volleyball
.
vine.object({
discipline: vine.enum(['volleyball', 'handball']),
volleyballLevel: vine
.enum(['senior', 'u21', 'u19', 'u17'])
.optional()
.requiredWhen('discipline', '=', 'volleyball')
})
The comparison operator can be one of the following.
in
accepts an array of values for comparison.notIn
accepts an array of values for comparison.=
accepts a literal value to perform an equality check.!=
accepts a literal value to perform a non-equality check.>
accepts a numeric value to compare two numbers.<
accepts a numeric value to compare two numbers.>=
accepts a numeric value to compare two numbers.<=
accepts a numeric value to compare two numbers.
You may use a callback with the requiredWhen
rule to express complex scenarios. Make sure to return true
to mark the field as required and false
to keep it optional.
vine.object({
address: vine
.string()
.requiredWhen((field) => {
if (field.parent.country !== 'USA') {
return false
}
return 'state' in field.parent && 'city' in field.parent
})
})
requiredIfExists
The requiredIfExists
method marks the field as required when the other field's value is not undefined
or null
.
vine.object({
password: vine
.string()
.optional()
.requiredIfExists('email')
})
You may also pass an array of field names to check if all the fields are defined before marking the current field as required.
vine.object({
address: vine
.string()
.optional()
.requiredIfExists(['state', 'city'])
})
requiredIfAnyExists
The requiredIfAnyExists
method marks the field as required when any of the expected fields are present with a value other than undefined
or null
.
vine.object({
password: vine
.string()
.optional()
.requiredIfAnyExists(['email', 'username'])
})
requiredIfMissing
The requiredIfMissing
method is the opposite of the requiredIfExists
method. It marks the field as required when all the mentioned fields are missing.
vine.object({
address: vine.string().optional(),
pincode: vine
.string()
.optional()
.requiredIfMissing('address')
})
requiredIfAnyMissing
The requiredIfAnyMissing
method marks the field as required when any of the expected fields are missing.
vine.object({
username: vine.string().optional(),
email: vine.string().optional(),
legacyAccountId: vine
.string()
.optional()
.requiredIfAnyMissing(['email', 'username'])
})