Array type
Ensure the value of a field is a valid JavaScript array. You must define the type of properties the array should contain.
In the following example, we expect the value of categories
to be an array of numbers.
import vine from '@vinejs/vine'
const schema = vine.object({
categories: vine.array(vine.number())
})
Using the following modifiers, you may mark the array as optional
or nullable
.
See also: Working with undefined
and null
values
{
categories: vine
.array(vine.number())
.nullable()
}
{
categories: vine
.array(vine.number())
.optional()
}
Creating an array of objects
Since the vine.array
method accepts any valid VineJS type, you may create an array of objects, as shown in the following example.
import vine from '@vinejs/vine'
const schema = vine.object({
contacts: vine.array(
vine.object({
id: vine.number(),
is_primary: vine.boolean(),
})
),
})
Creating an array of unions
An array can also accept a union type. In the following example, each contact can be an email or phone contact.
See also: Union type
/**
* Re-usable helper to check if the field value
* is an object and has a matching type
*/
function hasType(value: unknown, type: string) {
return vine.helpers.isObject(value) && value.type === type
}
/**
* Schema type for email contact
*/
const emailContact = vine.object({
type: vine.literal('email'),
email: vine.string().email()
})
/**
* Schema type for phone contact
*/
const phoneContact = vine.object({
type: vine.literal('phone'),
phone: vine.string().mobile()
})
/**
* Define a contact union with conditionals and
* their associated schema
*/
const contact = vine.union([
vine.union.if((value) => hasType(value, 'email'), emailContact),
vine.union.if((value) => hasType(value, 'phone'), phoneContact)
])
const schema = vine.object({
contacts: vine.array(contact)
})
In the above example, we have a union with two conditionals.
- The first one checks for
type === 'email
and uses theemailContact
schema. - And the second one checks for
type === 'phone'
and uses thephoneContact
schema.
An error will be raised if the type
property is missing or has a different value. Also, you can report a custom error by defining an otherwise
clause.
const contact = vine.union([
vine.union.if((value) => hasType(value, 'email'), emailContact),
vine.union.if((value) => hasType(value, 'phone'), phoneContact)
])
.otherwise((_, field) => {
field.report(
'Invalid contact. Either provide an email or a phone number',
'unknown_contact_type',
field
)
})
The field.report
method marks the field under validation as invalid and reports an error to the error reporter. It accepts the following arguments.
- The default error message.
- The error code. The code may be used to define custom error messages.
- And the field context.
Defining error messages
You may define custom error messages for the following array-based rules.
const messages = {
'array': 'The {{ field }} field must be an array',
'array.minLength': 'The {{ field }} field must have at least {{ min }} items',
'array.maxLength': 'The {{ field }} field must not have more than {{ max }} items',
'array.fixedLength': 'The {{ field }} field must contain {{ size }} items',
'notEmpty': 'The {{ field }} field must not be empty',
'distinct': 'The {{ field }} field has duplicate values',
}
vine.messagesProvider = new SimpleMessagesProvider(messages)
Validations
Following is the list of validation rules you can apply on an array.
minLength
Enforce the array to have the expected minimum length.
const schema = vine.object({
categories: vine.array(
vine.number()
).minLength(1)
})
maxLength
Enforce the array to have the expected maximum length.
const schema = vine.object({
categories: vine.array(
vine.number()
).maxLength(10)
})
fixedLength
Enforce the array to have a fixed length.
const schema = vine.object({
categories: vine.array(
vine.number()
).fixedLength(4)
})
notEmpty
Ensure the array has one or more values.
const schema = vine.object({
categories: vine.array(
vine.number()
).notEmpty()
})
distinct
Validate array children to have distinct/unique values. In the case of an array of objects, you may define the object property names to check for uniqueness.
In the following example, we expect the categories
array to have unique category ids.
const schema = vine.object({
categories: vine
.array(
vine.number()
)
.distinct()
})
In the following example, we expect users inside the array to have unique emails.
const schema = vine.object({
users: vine
.array(
vine.object({
email: vine.string(),
password: vine.string()
})
)
.distinct('email')
})
Finally, you may define composite keys to check for unique elements.
const schema = vine.object({
users: vine
.array(
vine.object({
email: vine.string(),
company_id: vine.number(),
password: vine.string()
})
)
.distinct(['email', 'company_id'])
}
Treatment of null
and undefined
items
Array items with null
and undefined
values will be skipped during the uniqueness check. So, for example, the following array will pass the distinct
validation.
/**
* Null values will be ignored
*/
const categories = [1, 8, null, 12, null, 2]
Treatment of objects with missing keys
Similarly, in the case of an array of objects, the object item will be skipped if it does contain all the fields required for the uniqueness check. For example, the following array will pass the distinct
validation.
const fields = ['email', 'company_id']
const users = [
/**
* Skipped because the object is missing the company_id
*/
{
email: 'foo@bar.com',
},
/**
* Skipped because the object is missing the company_id
*/
{
email: 'foo@bar.com',
},
]
Mutations
Following is the list of mutations you can perform on an array. As the name suggests, mutations normalize or change the input value and do not perform any validations.
compact
Remove empty strings
, null
, and undefined
values from the array. Applying the compact
mutation before the validation rules is recommended.
const schema = vine.object({
categories: vine
.array(
vine.number()
)
.compact()
})