when
Applies rules to the field depending on the value of another field.
Error codes: the errors of the rules of the selected branch, or NOT_ALLOWED_VALUE in the switch form when the value of the other field is empty or not one of the cases.
{
"vat_number": "REQUIRED"
}There are two forms, both positional:
{ when: [REFERENCE, CONDITION, RULES_IF_TRUE, RULES_IF_FALSE] } // RULES_IF_FALSE is optional
{ when: [REFERENCE, CASES] }The number of arguments selects the form: 2 is the switch form, 3 or 4 is the condition form. Fewer than 2 arguments, or CASES that is not an object, is a schema error. Don't pass arguments after the 4th: what happens to them depends on the implementation.
REFERENCE is a reference to another field. CONDITION, RULES_IF_TRUE, RULES_IF_FALSE and the values of CASES are rules in any form that a field accepts: a rule name, a rule object or a list of rules. An empty list [] is a schema error: use 'any' for a branch or a case without rules.
Condition form
- The condition is true when the referenced value is not empty and passes the
CONDITIONrules. TheCONDITIONrules run on the referenced value like the rules of a field: in order, the output of one rule is the input of the next (so['boolean', { eq: true }]works for"1"), and their output is discarded. - The condition itself checks that the value is not empty, so
requiredandnot_emptyadd nothing to it, and the condition{ eq: 'company' }ontypeis false whentypeis missing (the rule alone would pass an empty value). To check only that the other field is filled, write'required'. - Only a missing field,
nulland""are empty:false,0,"0"and" "are filled. So a checkbox needs['boolean', { eq: true }], and a value of spaces counts as filled unless the validator trims the input. - When the condition is true, the field is validated with
RULES_IF_TRUE, otherwise withRULES_IF_FALSE. - Without
RULES_IF_FALSE, a false condition means no rules: the value passes and stays in the output unchanged.
WARNING
With 3 arguments, a false condition lets any value through unchecked, even an object, like any. If the field may only be sent when the condition is true, prefer the 4th argument: { eq: '' } forbids the field, other rules check it.
{ vat_number: { when: ['type', { eq: 'company' }, ['required', 'string'], { eq: '' }] } }Switch form
- If the referenced value is empty, no case can be chosen: an empty validated value passes and stays as it is (the referenced field reports its own
REQUIRED), any other value givesNOT_ALLOWED_VALUE. Otherwise an unchecked value, a whole object among them, would pass. - Otherwise, the referenced value must be a primitive value whose string form is a key of
CASES. The field is validated with the rules of that key. - A referenced value that is not a key of
CASES, or is not a primitive value, givesNOT_ALLOWED_VALUEon the validated field, unless the validated value is empty. CASESmust have at least one key, otherwise it is a schema error.
Branches
The branch gets the value as it is, including empty values, so required works in it, and { eq: '' } forbids the field: all rules skip empty values, so it accepts only an empty value (there is no absent rule, { eq: '' } does the same). Its errors and output are the errors and output of the field.
Other fields in the rules
The CONDITION rules check the referenced value, and the branches check the validated value, but both see the containing object of the validated field, like its other rules: when is transparent, like aliases and or. This matters for rules that read other fields, such as equal_to_field, required_if or another when, also when the reference is a path:
{
seller_country: 'required',
address: { nested_object: { country: 'required' } },
vat: { when: ['address/country', { equal_to_field: 'seller_country' }, 'required'] }
}Here seller_country is the sibling of vat, not of country: the VAT number is required when the address is in the country of the seller.
Examples
Email or phone: if the phone is given, the email is only checked, otherwise it is required.
{
email: { when: ['phone', 'required', 'email', ['required', 'email']] },
phone: { when: ['email', 'required', 'string', ['required', 'string']] }
}A VAT number is required for companies and not allowed for anyone else.
{
vat_number: { when: ['type', { eq: 'company' },
['required', { like: '^[A-Z]{2}[0-9]{8,12}$' }], { eq: '' }] }
}A checkbox: "1", "true" and true all turn the condition on.
{
email: ['email', { when: ['subscribe', ['boolean', { eq: true }], 'required'] }]
}A switch: the type is outside the data object, which variable_object cannot do.
{
type: ['required', { one_of: ['card', 'bank'] }],
data: ['required', { when: ['type', {
card: { nested_object: { number: ['required', 'credit_card'] } },
bank: { nested_object: { iban: ['required', 'iban'] } }
}] }]
}