0
# Custom Validators and Parameters
1
2
System for creating custom validation functions with parameter metadata support, enabling reusable and configurable validation logic.
3
4
## Capabilities
5
6
### withParams Function
7
8
Higher-order function for adding parameter metadata to validators, enabling parameter inspection and enhanced error reporting.
9
10
```javascript { .api }
11
/**
12
* Adds parameter metadata to a validator function
13
* @param params - Object containing parameter metadata
14
* @param validator - Validator function to wrap
15
*/
16
function withParams(
17
params: object,
18
validator: (value: any, parentVm?: any) => boolean | Promise<boolean>
19
): (value: any, parentVm?: any) => boolean | Promise<boolean>;
20
21
/**
22
* Closure-based parameter addition for dynamic parameter scenarios
23
* @param closure - Function that receives addParams function and returns validator
24
*/
25
function withParams(
26
closure: (addParams: (params: object) => void) => (value: any, parentVm?: any) => boolean | Promise<boolean>
27
): (value: any, parentVm?: any) => boolean | Promise<boolean>;
28
```
29
30
## Creating Custom Validators
31
32
### Simple Custom Validators
33
34
Basic custom validators without parameters.
35
36
**Usage:**
37
38
```javascript
39
import { withParams } from 'vuelidate'
40
41
// Simple validator without parameters
42
const strongPassword = (value) => {
43
if (!value) return true // allow empty, combine with required if needed
44
45
const hasUpper = /[A-Z]/.test(value)
46
const hasLower = /[a-z]/.test(value)
47
const hasNumber = /\d/.test(value)
48
const hasSpecial = /[!@#$%^&*(),.?":{}|<>]/.test(value)
49
50
return hasUpper && hasLower && hasNumber && hasSpecial
51
}
52
53
// Usage in component
54
validations: {
55
password: {
56
required,
57
strongPassword
58
}
59
}
60
```
61
62
### Parameterized Custom Validators
63
64
Custom validators that accept configuration parameters.
65
66
**Usage:**
67
68
```javascript
69
import { withParams } from 'vuelidate'
70
71
// Validator factory with parameters
72
const customMinLength = (min) => withParams(
73
{ type: 'customMinLength', min },
74
(value) => {
75
return !value || value.length >= min
76
}
77
)
78
79
// Date range validator
80
const dateRange = (startDate, endDate) => withParams(
81
{ type: 'dateRange', startDate, endDate },
82
(value) => {
83
if (!value) return true
84
const date = new Date(value)
85
return date >= new Date(startDate) && date <= new Date(endDate)
86
}
87
)
88
89
// Usage in component
90
validations: {
91
username: {
92
customMinLength: customMinLength(3)
93
},
94
eventDate: {
95
dateRange: dateRange('2024-01-01', '2024-12-31')
96
}
97
}
98
```
99
100
### Contextual Validators
101
102
Validators that access component context and other properties.
103
104
**Usage:**
105
106
```javascript
107
import { withParams } from 'vuelidate'
108
109
// Validator that accesses other component data
110
const dependsOnOtherField = withParams(
111
{ type: 'dependsOnOtherField' },
112
function(value, parentVm) {
113
// Access other properties via parentVm or this
114
const otherValue = parentVm.otherField
115
return !value || value !== otherValue
116
}
117
)
118
119
// Age-based validation
120
const ageBasedValidation = withParams(
121
{ type: 'ageBasedValidation' },
122
function(value, parentVm) {
123
const age = parentVm.age
124
if (age < 18) {
125
return !value || value.length <= 10 // shorter value for minors
126
}
127
return !value || value.length <= 50 // longer value for adults
128
}
129
)
130
131
// Usage in component
132
validations: {
133
field1: { dependsOnOtherField },
134
comment: { ageBasedValidation }
135
}
136
```
137
138
### Async Custom Validators
139
140
Validators that perform asynchronous operations like API calls.
141
142
**Usage:**
143
144
```javascript
145
import { withParams } from 'vuelidate'
146
147
// Async username availability check
148
const uniqueUsername = withParams(
149
{ type: 'uniqueUsername' },
150
async (value) => {
151
if (!value) return true
152
153
try {
154
const response = await fetch(`/api/check-username?username=${value}`)
155
const data = await response.json()
156
return data.available
157
} catch (error) {
158
// Handle error - could return false or true depending on strategy
159
return false
160
}
161
}
162
)
163
164
// Async email verification
165
const verifyEmail = withParams(
166
{ type: 'verifyEmail' },
167
(value) => {
168
if (!value) return true
169
170
return new Promise((resolve) => {
171
// Simulate API call
172
setTimeout(() => {
173
const isValid = value.includes('@') && !value.includes('spam')
174
resolve(isValid)
175
}, 1000)
176
})
177
}
178
)
179
180
// Usage in component
181
validations: {
182
username: {
183
required,
184
uniqueUsername
185
},
186
email: {
187
required,
188
email,
189
verifyEmail
190
}
191
}
192
```
193
194
### Closure-based Parameter Addition
195
196
Advanced parameter management using the closure form of `withParams`.
197
198
**Usage:**
199
200
```javascript
201
import { withParams } from 'vuelidate'
202
203
// Complex validator with dynamic parameters
204
const complexValidator = withParams((addParams) => {
205
return function(value, parentVm) {
206
// Add different parameters based on conditions
207
if (!value) {
208
addParams({ type: 'complex', reason: 'empty' })
209
return true
210
}
211
212
if (value.length < 5) {
213
addParams({ type: 'complex', reason: 'tooShort', minLength: 5 })
214
return false
215
}
216
217
if (!/^[a-zA-Z]/.test(value)) {
218
addParams({ type: 'complex', reason: 'mustStartWithLetter' })
219
return false
220
}
221
222
addParams({ type: 'complex', reason: 'valid' })
223
return true
224
}
225
})
226
227
// Validator with conditional sub-validations
228
const conditionalValidator = withParams((addParams) => {
229
return function(value, parentVm) {
230
const userType = parentVm.userType
231
232
addParams({ type: 'conditional', userType })
233
234
if (userType === 'admin') {
235
addParams({ minLength: 10 })
236
return !value || value.length >= 10
237
} else {
238
addParams({ minLength: 5 })
239
return !value || value.length >= 5
240
}
241
}
242
})
243
```
244
245
## Parameter Access
246
247
### Accessing Validator Parameters
248
249
Parameters added via `withParams` are accessible through the validation state.
250
251
**Usage:**
252
253
```javascript
254
// In component template or methods
255
export default {
256
// ... component setup
257
computed: {
258
passwordErrors() {
259
const validation = this.$v.password
260
261
if (validation.$error) {
262
const errors = []
263
264
// Access parameters from custom validators
265
if (!validation.customMinLength) {
266
const params = validation.customMinLength.$params
267
errors.push(`Minimum length is ${params.min} characters`)
268
}
269
270
if (!validation.strongPassword) {
271
errors.push('Password must contain uppercase, lowercase, number, and special character')
272
}
273
274
return errors
275
}
276
277
return []
278
}
279
}
280
}
281
```
282
283
### Parameter Inspection
284
285
Using parameters for dynamic error messages and UI behavior.
286
287
**Usage:**
288
289
```javascript
290
// Generic error message generator
291
function generateErrorMessage(fieldName, validation) {
292
for (const ruleName in validation) {
293
if (ruleName.startsWith('$') || validation[ruleName]) continue
294
295
const rule = validation[ruleName]
296
const params = rule.$params
297
298
if (params) {
299
switch (params.type) {
300
case 'minLength':
301
return `${fieldName} must be at least ${params.min} characters`
302
case 'dateRange':
303
return `${fieldName} must be between ${params.startDate} and ${params.endDate}`
304
case 'uniqueUsername':
305
return `${fieldName} is already taken`
306
default:
307
return `${fieldName} is invalid`
308
}
309
}
310
}
311
312
return `${fieldName} is invalid`
313
}
314
315
// Usage in component
316
computed: {
317
usernameError() {
318
return this.$v.username.$error
319
? generateErrorMessage('Username', this.$v.username)
320
: null
321
}
322
}
323
```
324
325
## Helper Utilities
326
327
### Common Validator Patterns
328
329
Reusable patterns for building custom validators.
330
331
```javascript { .api }
332
/**
333
* Core required check utility (exported from validators/common)
334
*/
335
function req(value: any): boolean;
336
337
/**
338
* Type-agnostic length utility (exported from validators/common)
339
*/
340
function len(value: any): number;
341
342
/**
343
* Resolve referenced values from component (exported from validators/common)
344
*/
345
function ref(reference: string | Function, vm: any, parentVm: any): any;
346
347
/**
348
* Regex-based validator template (exported from validators/common)
349
*/
350
function regex(type: string, expr: RegExp): (value: any) => boolean;
351
```
352
353
**Usage:**
354
355
```javascript
356
import { withParams, helpers } from 'vuelidate'
357
358
const { req, len, ref, regex } = helpers
359
360
// Using helper utilities
361
const customRequired = withParams(
362
{ type: 'customRequired' },
363
(value) => req(value)
364
)
365
366
const customLength = (min, max) => withParams(
367
{ type: 'customLength', min, max },
368
(value) => {
369
const length = len(value)
370
return length >= min && length <= max
371
}
372
)
373
374
const phoneNumber = regex('phoneNumber', /^\+?[\d\s\-\(\)]+$/)
375
376
const dependentField = (otherField) => withParams(
377
{ type: 'dependentField', otherField },
378
function(value, parentVm) {
379
const otherValue = ref(otherField, this, parentVm)
380
return !value || value !== otherValue
381
}
382
)
383
```