Skip to main content

Validators

Tess UI Library fornisce un set di validatori personalizzati per i form Angular.

Validatori Sincroni

emailValidator

Valida che un valore sia un indirizzo email valido.

import { emailValidator } from '@tess-ui-library/core';
import { FormControl } from '@angular/forms';

const control = new FormControl('', emailValidator);
control.setValue('invalid-email');
console.log(control.errors); // { email: true }

control.setValue('user@example.com');
console.log(control.errors); // null

urlValidator

Valida che un valore sia un URL valido.

import { urlValidator } from '@tess-ui-library/core';

const control = new FormControl('', urlValidator);
control.setValue('not-a-url');
console.log(control.errors); // { url: true }

control.setValue('https://example.com');
console.log(control.errors); // null

phoneValidator

Valida che un valore sia un numero di telefono valido (formati internazionali).

import { phoneValidator } from '@tess-ui-library/core';

const control = new FormControl('', phoneValidator);
control.setValue('123');
console.log(control.errors); // { phone: true }

control.setValue('+39 333 1234567');
console.log(control.errors); // null

alphanumericValidator

Valida che un valore contenga solo caratteri alfanumerici.

import { alphanumericValidator } from '@tess-ui-library/core';

const control = new FormControl('', alphanumericValidator);
control.setValue('Hello@World');
console.log(control.errors); // { alphanumeric: true }

control.setValue('HelloWorld123');
console.log(control.errors); // null

matchValidator(fieldName: string)

Valida che due campi abbiano lo stesso valore (utile per conferma password).

import { matchValidator } from '@tess-ui-library/core';
import { FormGroup, FormControl } from '@angular/forms';

const form = new FormGroup({
password: new FormControl(''),
confirmPassword: new FormControl('', matchValidator('password')),
});

form.patchValue({
password: 'secret123',
confirmPassword: 'different',
});
console.log(form.get('confirmPassword')?.errors); // { match: true }

form.patchValue({
confirmPassword: 'secret123',
});
console.log(form.get('confirmPassword')?.errors); // null

rangeValidator(min: number, max: number)

Valida che un numero sia compreso in un intervallo.

import { rangeValidator } from '@tess-ui-library/core';

const control = new FormControl('', rangeValidator(18, 65));
control.setValue(16);
console.log(control.errors); // { range: { min: 18, max: 65, actual: 16 } }

control.setValue(25);
console.log(control.errors); // null

dateRangeValidator(minDate?: Date, maxDate?: Date)

Valida che una data sia compresa in un intervallo.

import { dateRangeValidator } from '@tess-ui-library/core';

const minDate = new Date('2024-01-01');
const maxDate = new Date('2024-12-31');

const control = new FormControl('', dateRangeValidator(minDate, maxDate));
control.setValue(new Date('2023-06-15'));
console.log(control.errors); // { dateRange: { min: minDate, max: maxDate } }

control.setValue(new Date('2024-06-15'));
console.log(control.errors); // null

fileSizeValidator(maxSizeInBytes: number)

Valida la dimensione massima di un file.

import { fileSizeValidator } from '@tess-ui-library/core';

const control = new FormControl('', fileSizeValidator(1024 * 1024)); // 1MB

// In un file input change handler
onFileChange(event: Event) {
const file = (event.target as HTMLInputElement).files?.[0];
if (file) {
this.control.setValue(file);
}
}

fileTypeValidator(allowedTypes: string[])

Valida il tipo MIME di un file.

import { fileTypeValidator } from '@tess-ui-library/core';

const control = new FormControl('',
fileTypeValidator(['image/png', 'image/jpeg', 'image/gif'])
);

Validatori Compositi

composeValidators(...validators: ValidatorFn[])

Compone più validatori in uno solo.

import { composeValidators, emailValidator, urlValidator } from '@tess-ui-library/core';
import { Validators } from '@angular/forms';

const control = new FormControl('',
composeValidators(
Validators.required,
Validators.minLength(5),
emailValidator
)
);

Validatori Condizionali

conditionalValidator(condition: () => boolean, validator: ValidatorFn)

Applica un validatore solo quando una condizione è vera.

import { conditionalValidator } from '@tess-ui-library/core';
import { Validators } from '@angular/forms';

const form = new FormGroup({
requiresDetails: new FormControl(false),
details: new FormControl('',
conditionalValidator(
() => form.get('requiresDetails')?.value === true,
Validators.required
)
),
});

Validatori Cross-Field

passwordMatchValidator

Validatore per FormGroup che verifica che password e confirmPassword coincidano.

import { passwordMatchValidator } from '@tess-ui-library/core';
import { FormGroup, FormControl } from '@angular/forms';

const form = new FormGroup({
password: new FormControl(''),
confirmPassword: new FormControl(''),
}, { validators: passwordMatchValidator });

form.patchValue({
password: 'secret123',
confirmPassword: 'different',
});
console.log(form.errors); // { passwordMismatch: true }

form.patchValue({
confirmPassword: 'secret123',
});
console.log(form.errors); // null

dateRangeGroupValidator(startDateKey: string, endDateKey: string)

Valida che una data di inizio sia precedente a una data di fine.

import { dateRangeGroupValidator } from '@tess-ui-library/core';
import { FormGroup, FormControl } from '@angular/forms';

const form = new FormGroup({
startDate: new FormControl(new Date('2024-06-01')),
endDate: new FormControl(new Date('2024-05-01')),
}, { validators: dateRangeGroupValidator('startDate', 'endDate') });

console.log(form.errors); // { dateRangeInvalid: true }

Uso con AutoForm

I validatori possono essere usati direttamente nei modelli AutoForm:

import { FormModel } from '@tess-ui-library/core';

const formModel: FormModel = {
id: 'user-form',
fields: [
{
key: 'email',
type: 'email',
label: 'Email',
validation: {
required: true,
custom: emailValidator, // Usa validatore custom
},
},
{
key: 'phone',
type: 'text',
label: 'Telefono',
validation: {
custom: phoneValidator,
},
},
{
key: 'age',
type: 'number',
label: 'Età',
validation: {
custom: rangeValidator(18, 100),
},
},
],
};

Creazione Validatori Personalizzati

Validatore Sincrono

import { AbstractControl, ValidatorFn, ValidationErrors } from '@angular/forms';

export function customValidator(param: string): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
const value = control.value;

if (!value) {
return null; // Non validare se vuoto (usa 'required' per questo)
}

// La tua logica di validazione
const isValid = value.includes(param);

return isValid ? null : {
customError: {
requiredValue: param,
actualValue: value,
},
};
};
}

Validatore Asincrono

import { AbstractControl, AsyncValidatorFn, ValidationErrors } from '@angular/forms';
import { Observable, of, delay, map } from 'rxjs';

export function asyncCustomValidator(
checkFn: (value: any) => Observable<boolean>
): AsyncValidatorFn {
return (control: AbstractControl): Observable<ValidationErrors | null> => {
if (!control.value) {
return of(null);
}

return checkFn(control.value).pipe(
map(exists => (exists ? { asyncError: true } : null))
);
};
}

Best Practices

  1. Riutilizza validatori: Crea validatori riutilizzabili per logiche comuni
  2. Messaggi chiari: Fornisci messaggi di errore descrittivi
  3. Validazione incrementale: Usa validatori sincroni prima di quelli asincroni
  4. Performance: Usa updateOn: 'blur' per validatori costosi
  5. Composizione: Usa composeValidators per combinare più validatori
  6. Type-safety: Definisci interfacce TypeScript per i tuoi dati di form

Vedi Anche