ValidationService
Panoramica
ValidationService è il motore di validazione di @pzeta/vue-form. Espone metodi statici per validare valori con regole pipe-separated, tradurre le chiavi errore i18n e registrare validatori custom.
Quando usare ValidationService invece di useValidation:
| Caso | Strumento consigliato |
|---|---|
| Validazione reattiva di un campo Vue | useValidation |
| Validazione server-side o in un service | ValidationService |
| Validazione in un test unitario | ValidationService |
| Tradurre errori già ottenuti | ValidationService.translateErrors() |
| Registrare un validatore custom | ValidationService.registerValidator() |
| Validare senza i18n (fallback leggibili) | ValidationService.validateWithFallback() |
API
import { ValidationService } from '@pzeta/vue-form'
Metodi statici
export class ValidationService {
// Valida un valore con regole pipe-separated
static validate(value: unknown, rules: string): ValidationResult
// Valida, traduce e restituisce tutto in un'operazione
static validateAndTranslate(
value: unknown,
rules: string,
t: TranslateFunction,
): TranslatedValidationResult
// Valida con messaggi leggibili senza i18n
static validateWithFallback(value: unknown, rules: string): TranslatedValidationResult
// Traduce una singola chiave errore
static translateError(error: string, t: TranslateFunction): string
// Traduce un array di chiavi errore
static translateErrors(errors: string[], t: TranslateFunction): string[]
// Estrae il messaggio fallback da una chiave i18n (senza t())
static extractFallback(key: string): string
// Registra un validatore custom
static registerValidator(name: string, validator: Validator): void
// Lista tutti i validatori disponibili
static getAvailableValidators(): string[]
}
Interfacce
export interface ValidationResult {
isValid: boolean
errors: string[] // chiavi i18n (es. "validation.core.required")
}
export interface TranslatedValidationResult extends ValidationResult {
translatedErrors: string[] // messaggi tradotti/leggibili
}
export type TranslateFunction = (
key: string,
params?: Record<string, string | number>,
) => string
Sintassi regole pipe-separated
Le regole vengono passate come stringa con | come separatore. Vengono eseguite in sequenza; la validazione si ferma al primo errore per regola.
'required|email'
'required|min:8|max:100'
'required|integer|between:1,100'
'required|codicefiscale'
Regole con parametri
| Formato | Esempio | Descrizione |
|---|---|---|
regola | required | Senza parametri |
regola:valore | min:5 | Un parametro numerico |
regola:val1,val2 | between:1,100 | Due parametri |
regola:stringa | pattern:[A-Z]+ | Parametro stringa |
Validatori disponibili (selezione)
| Regola | Parametri | Descrizione |
|---|---|---|
required | — | Campo obbligatorio |
min | :n | Minimo n caratteri (stringa) o valore n (numero) |
max | :n | Massimo n caratteri o valore |
length | :n | Lunghezza esatta |
between | :min,max | Valore compreso tra min e max |
email | — | Formato email valido |
url | — | URL valido |
integer | — | Numero intero |
numeric | — | Valore numerico |
positive | — | Numero positivo |
alpha | — | Solo lettere |
alphanumeric | — | Lettere e numeri |
codicefiscale | — | Codice fiscale italiano |
partitaiva | — | Partita IVA italiana |
iban | — | IBAN valido |
password | — | Password con requisiti standard |
strong | — | Password forte (12+ caratteri, tutti i tipi) |
uuid | — | UUID valido |
enum | :v1,v2,... | Valore tra quelli specificati |
regex | :pattern | Match espressione regolare |
Per la lista completa usare ValidationService.getAvailableValidators().
Flusso traduzione errori
validate() restituisce sempre chiavi i18n grezze. Il formato è:
"validation.categoria.chiave" // senza parametri
"validation.core.min|min:5" // con un parametro
"validation.core.between|min:1,max:100" // con più parametri
La parte dopo il | contiene i parametri nel formato nome:valore separati da virgola. translateError() e translateErrors() li estraggono automaticamente e li passano alla funzione t().
Metodi dettagliati
validate()
Valida e restituisce chiavi i18n grezze. Da usare quando si vuole gestire la traduzione separatamente.
const result = ValidationService.validate('test@example.com', 'required|email')
// { isValid: true, errors: [] }
const invalid = ValidationService.validate('', 'required|email')
// { isValid: false, errors: ['validation.core.required'] }
const tooShort = ValidationService.validate('ab', 'required|min:5')
// { isValid: false, errors: ['validation.core.minString|min:5'] }
validateAndTranslate()
Valida e traduce in un'unica operazione. Richiede la funzione t di @pzeta/vue-i18n.
import { useI18n } from '@pzeta/vue-i18n'
const { t } = useI18n()
const result = ValidationService.validateAndTranslate(
'',
'required|email',
t,
)
// {
// isValid: false,
// errors: ['validation.core.required'],
// translatedErrors: ['Questo campo è obbligatorio'],
// }
validateWithFallback()
Valida con messaggi leggibili senza bisogno di t(). Utile in contesti server-side, test o log.
const result = ValidationService.validateWithFallback('', 'required|min:8')
// {
// isValid: false,
// errors: ['validation.core.required'],
// translatedErrors: ['Required'],
// }
translateError() e translateErrors()
Traducono chiavi già ottenute da validate(), estraendo automaticamente i parametri.
const { t } = useI18n()
// Singolo errore con parametro
const msg = ValidationService.translateError('validation.core.minString|min:5', t)
// "Il campo deve contenere almeno 5 caratteri"
// Array di errori
const msgs = ValidationService.translateErrors(
['validation.core.required', 'validation.format.email'],
t,
)
// ['Questo campo è obbligatorio', 'Inserisci un indirizzo email valido']
extractFallback()
Estrae un messaggio di fallback leggibile da una chiave, senza t().
ValidationService.extractFallback('validation.core.required')
// "Required"
ValidationService.extractFallback('validation.core.minString|min:5')
// "Min 5"
registerValidator()
Registra un validatore custom con un nome che può essere usato nelle regole pipe-separated. La forma del Validator è { fn: ValidatorFn, parameterized: boolean } dove fn ritorna un ValidationResult (non true | string).
import { ValidationService } from '@pzeta/vue-form'
import type { Validator } from '@pzeta/vue-form'
// Validatore senza parametri
const codiceBudget: Validator = {
fn: (value: unknown) => {
const isValid = typeof value === 'string' && /^BDG-\d{4}-[A-Z]{2}$/.test(value)
return {
isValid,
errors: isValid ? [] : ['validation.custom.codiceBudget'],
}
},
parameterized: false,
}
ValidationService.registerValidator('codiceBudget', codiceBudget)
// Validatore con parametro (sintassi `nome:parametro`)
ValidationService.registerValidator('divisibleBy', {
fn: (value, divisor) => {
const num = Number(value)
const div = Number(divisor)
const isValid = !Number.isNaN(num) && !Number.isNaN(div) && num % div === 0
return {
isValid,
errors: isValid ? [] : [`validation.custom.divisibleBy|divisor:${divisor ?? ''}`],
}
},
parameterized: true,
})
// Ora disponibili nelle regole
ValidationService.validate('BDG-2024-AB', 'required|codiceBudget')
ValidationService.validate(15, 'divisibleBy:5')
skipEmpty: per validatori opzionali (che devono passare con valori null / undefined / ''), usa l'helper esportato skipEmpty(value) all'inizio di fn. Convenzione: solo required valida i valori vuoti — gli altri validatori li trattano come "saltabili".getAvailableValidators()
Restituisce la lista di tutti i validatori registrati (built-in + custom).
const validatori = ValidationService.getAvailableValidators()
console.log(validatori)
// ['required', 'min', 'max', 'email', 'url', 'integer', ..., 'codiceBudget']
Esempi completi
Validazione on-submit con traduzione
import { ValidationService } from '@pzeta/vue-form'
import { useI18n } from '@pzeta/vue-i18n'
const { t } = useI18n()
const validateForm = (formData: { email: string; password: string }) => {
const emailResult = ValidationService.validateAndTranslate(
formData.email,
'required|email',
t,
)
const passwordResult = ValidationService.validateAndTranslate(
formData.password,
'required|min:8|password',
t,
)
return {
isValid: emailResult.isValid && passwordResult.isValid,
errors: {
email: emailResult.translatedErrors,
password: passwordResult.translatedErrors,
},
}
}
Validazione in un service backend (senza i18n)
import { ValidationService } from '@pzeta/vue-form'
export class AnagraficaService {
validateInput(data: { codiceFiscale: string; email: string }) {
const cfResult = ValidationService.validateWithFallback(
data.codiceFiscale,
'required|codicefiscale',
)
const emailResult = ValidationService.validateWithFallback(
data.email,
'required|email',
)
if (!cfResult.isValid || !emailResult.isValid) {
throw new Error([
...cfResult.translatedErrors,
...emailResult.translatedErrors,
].join(', '))
}
}
}
Validatore custom con messaggi i18n
Per supportare traduzioni, il validatore deve restituire chiavi i18n registrate nel dizionario dell'app:
// Registrazione validatore (forma { fn, parameterized })
ValidationService.registerValidator('partitaIvaOrCf', {
fn: (value: unknown) => {
if (typeof value !== 'string' || value.trim() === '') {
return { isValid: false, errors: ['validation.core.required'] }
}
const cfResult = ValidationService.validate(value, 'codicefiscale')
const pivaResult = ValidationService.validate(value, 'partitaiva')
const isValid = cfResult.isValid || pivaResult.isValid
return {
isValid,
errors: isValid ? [] : ['validation.italian.cfOrPiva'],
}
},
parameterized: false,
})
// Uso nelle regole
ValidationService.validate('RSSMRA80A01H501U', 'required|partitaIvaOrCf')
// { isValid: true, errors: [] }
Note
- I validatori custom vengono aggiunti al registro globale: registrarli una volta al bootstrap dell'app (es. in
main.ts). validateWithFallback()usaextractFallback()internamente: il messaggio di fallback è derivato dal nome della chiave, non dal dizionario italiano. Per messaggi precisi usare semprevalidateAndTranslate().- Il formato dei parametri nelle chiavi errore (
"chiave|param:val") è stabile e parte dell'API pubblica.