Form Utilities
Tess UI Library fornisce un set completo di utilità per semplificare il lavoro con i form reattivi di Angular.
Async Validator Registry
Il servizio AsyncValidatorRegistry permette di registrare e gestire validatori asincroni dinamicamente.
Uso Base
import { Component, inject } from '@angular/core';
import { FormControl, ReactiveFormsModule } from '@angular/forms';
import { AsyncValidatorRegistry, CommonAsyncValidators } from '@tess-ui-library/core';
@Component({
selector: 'app-registration',
standalone: true,
imports: [ReactiveFormsModule],
template: `
<input [formControl]="emailControl" />
@if (emailControl.errors?.['uniqueEmail']) {
<span>Questa email è già in uso</span>
}
`
})
export class RegistrationComponent {
private validatorRegistry = inject(AsyncValidatorRegistry);
emailControl = new FormControl('', {
asyncValidators: this.validatorRegistry.getAsyncValidator('uniqueEmail')!
});
constructor() {
// Registra il validatore all'avvio dell'app (es. in APP_INITIALIZER)
this.validatorRegistry.registerAsyncValidator(
'uniqueEmail',
CommonAsyncValidators.uniqueEmail((email) =>
this.checkEmailExists(email)
)
);
}
private checkEmailExists(email: string): Promise<boolean> {
return this.http.get<boolean>(\`/api/users/check-email?email=\${email}\`)
.toPromise();
}
}
Registrazione Globale
È raccomandato registrare i validatori asincroni globalmente all'avvio dell'applicazione:
// app.config.ts
import { APP_INITIALIZER, ApplicationConfig } from '@angular/core';
import { AsyncValidatorRegistry, CommonAsyncValidators } from '@tess-ui-library/core';
import { UserService } from './services/user.service';
export function initializeValidators(
registry: AsyncValidatorRegistry,
userService: UserService
): () => void {
return () => {
registry.registerAsyncValidator(
'uniqueEmail',
CommonAsyncValidators.uniqueEmail((email) =>
userService.checkEmailExists(email)
)
);
registry.registerAsyncValidator(
'uniqueUsername',
CommonAsyncValidators.uniqueValue((username) =>
userService.checkUsernameExists(username)
)
);
};
}
export const appConfig: ApplicationConfig = {
providers: [
{
provide: APP_INITIALIZER,
useFactory: initializeValidators,
deps: [AsyncValidatorRegistry, UserService],
multi: true,
},
],
};
API
registerAsyncValidator(name: string, validator: AsyncValidatorFn): void
Registra un validatore asincrono con un nome specifico.
getAsyncValidator(name: string): AsyncValidatorFn | undefined
Recupera un validatore asincrono registrato per nome.
unregisterAsyncValidator(name: string): void
Rimuove un validatore asincrono registrato.
hasAsyncValidator(name: string): boolean
Verifica se un validatore asincrono è registrato con il nome specificato.
Common Async Validators
La libreria fornisce validatori asincroni pronti all'uso:
uniqueEmail(checkFn: (email: string) => Promise<boolean>)
Validatore per verificare l'unicità di un'email.
CommonAsyncValidators.uniqueEmail((email) =>
this.userService.checkEmailExists(email)
)
uniqueValue(checkFn: (value: any) => Promise<boolean>)
Validatore generico per verificare l'unicità di un valore.
CommonAsyncValidators.uniqueValue((username) =>
this.userService.checkUsernameExists(username)
)
Form Helpers
markAllAsTouched(form: FormGroup): void
Marca tutti i controlli di un form come "touched", utile per mostrare tutti gli errori di validazione.
import { markAllAsTouched } from '@tess-ui-library/core';
onSubmit() {
if (this.form.invalid) {
markAllAsTouched(this.form);
return;
}
// submit logic...
}
resetForm(form: FormGroup): void
Resetta un form ai suoi valori iniziali e marca tutti i controlli come "untouched" e "pristine".
import { resetForm } from '@tess-ui-library/core';
onCancel() {
resetForm(this.form);
}
getFormErrors(form: FormGroup): Record<string, any>
Estrae tutti gli errori di validazione da un form in un oggetto flat.
import { getFormErrors } from '@tess-ui-library/core';
const errors = getFormErrors(this.form);
console.log(errors);
// Output: { 'email': { required: true }, 'age': { min: { min: 18, actual: 16 } } }
Error Messages
getErrorMessage(errors: ValidationErrors, fieldLabel?: string): string
Converte gli errori di validazione in messaggi leggibili.
import { getErrorMessage } from '@tess-ui-library/core';
const emailControl = this.form.get('email');
if (emailControl?.errors) {
const message = getErrorMessage(emailControl.errors, 'Email');
console.log(message); // "Email is required"
}
Messaggi Personalizzati
Puoi configurare messaggi di errore personalizzati:
import { ERROR_MESSAGES } from '@tess-ui-library/core';
// Nel tuo app.config.ts
{
provide: ERROR_MESSAGES,
useValue: {
required: (field: string) => \`Il campo \${field} è obbligatorio\`,
email: () => 'Inserisci un indirizzo email valido',
minlength: (field: string, error: any) =>
\`\${field} deve avere almeno \${error.requiredLength} caratteri\`,
}
}
Input Masks
applyCurrencyMask(value: string): string
Applica una maschera di valuta a un valore.
import { applyCurrencyMask } from '@tess-ui-library/core';
const masked = applyCurrencyMask('1234.56');
console.log(masked); // "€ 1.234,56" (o formato locale)
applyPhoneMask(value: string): string
Applica una maschera telefonica a un valore.
import { applyPhoneMask } from '@tess-ui-library/core';
const masked = applyPhoneMask('1234567890');
console.log(masked); // "+1 (123) 456-7890"
Custom Masks
Puoi definire maschere personalizzate usando una direttiva:
import { Directive, HostListener } from '@angular/core';
@Directive({
selector: '[appCreditCardMask]',
standalone: true,
})
export class CreditCardMaskDirective {
@HostListener('input', ['$event'])
onInput(event: Event) {
const input = event.target as HTMLInputElement;
let value = input.value.replace(/\s/g, '');
// Aggiungi spazi ogni 4 cifre
const formatted = value.match(/.{1,4}/g)?.join(' ') || '';
input.value = formatted;
}
}
Best Practices
- Registra validatori globalmente: Usa
APP_INITIALIZERper registrare validatori asincroni all'avvio - Debounce validatori asincroni: Usa
updateOn: 'blur'odebounceTimeper evitare chiamate API eccessive - Messaggi di errore consistenti: Usa
ERROR_MESSAGEStoken per messaggi centralizzati - Form groups annidati: Usa
getFormErrorsper gestire errori in strutture complesse - Cleanup: Ricordati di fare unsubscribe dai validatori quando il componente viene distrutto