Die Formularvalidierung ist ein wesentlicher Bestandteil jeder Webanwendung, da sie sicherstellt, dass Benutzereingaben dem erwarteten Format entsprechen und verhindert, dass falsche Daten übermittelt werden. In Angular müssen Sie häufig Validierungsfehlermeldungen dynamisch anzeigen, und in mehrsprachigen Anwendungen ist es wichtig, diese Meldungen in der bevorzugten Sprache des Benutzers bereitzustellen.
Warum eine benutzerdefinierte Directive verwenden?
Directives in Angular sind leistungsstarke Werkzeuge zur Erweiterung des Verhaltens von DOM-Elementen. Die Verwendung einer Directive zur Handhabung der Formularvalidierung ermöglicht es uns, die Fehlermeldungslogik vom Formularcode zu trennen, was den Code modularer und einfacher zu warten macht. Darüber hinaus können wir in Kombination mit einem Übersetzungsdienst wie Transloco die Unterstützung mehrerer Sprachen für Fehlermeldungen nahtlos handhaben, ohne Code in Komponenten zu duplizieren.
Directive Code: FormErrorDirective
import { Directive, DoCheck, ElementRef, HostBinding, inject, Input, Renderer2 } from '@angular/core';
import { NgControl } from '@angular/forms';
import { TranslocoService } from '@ngneat/transloco';
@Directive({
selector: '[formControlName], [formControl]',
standalone: true,
})
export class FormErrorDirective implements DoCheck {
@Input() formControlName!: string;
private elementRef: ElementRef = inject(ElementRef);
private renderer: Renderer2 = inject(Renderer2);
private translocoService: TranslocoService = inject(TranslocoService);
private errorElement!: HTMLElement;
constructor(private ngControl: NgControl) {}
ngDoCheck(): void {
this.updateErrorDisplay();
}
@HostBinding('class.form-element__error')
get inValidClass(): boolean {
return (this.ngControl.control?.touched && this.ngControl.control.invalid) || false;
}
private updateErrorDisplay(): void {
const control = this.ngControl.control;
if (control?.untouched && control.root.invalid) {
return;
}
const errors = control?.errors;
if (errors) {
this.displayError(this.getErrorMessage(errors));
} else {
this.clearError();
}
}
private getErrorMessage(errors: any): string {
const firstErrorKey = Object.keys(errors)[0];
return this.translocoService.translate(
`${firstErrorKey}`,
errors[firstErrorKey]
);
}
private displayError(errorMessage: string): void {
if (!this.errorElement) {
this.createElement();
}
this.renderer.setProperty(this.errorElement, 'innerHTML', errorMessage);
this.renderer.appendChild(
this.elementRef.nativeElement.parentNode,
this.errorElement
);
}
private clearError(): void {
if (this.errorElement) {
this.renderer.removeChild(
this.elementRef.nativeElement.parentNode,
this.errorElement
);
this.errorElement = null!;
}
}
private createElement(): void {
this.clearError();
this.errorElement = this.renderer.createElement('span');
this.renderer.addClass(this.errorElement, 'form-element__error-message');
}
}
Schritt-für-Schritt-Anleitung
@Directive-Dekorator
Der @Directive-Dekorator definiert die Directive und deren Selektor, der Formularelemente mit formControlName oder formControl anvisiert.
NgControl und Formularsteuerungsbindung
Mit NgControl können wir den Zustand der Formularsteuerung (Gültigkeit, Berührung, etc.) abfragen, während @HostBinding eine CSS-Klasse anwendet, wenn das Steuerungselement ungültig und berührt ist.
Fehlerbehandlung
Der ngDoCheck-Lebenszyklus-Hook wird verwendet, um Änderungen im Validierungsstatus der Formularsteuerung zu erkennen. Die Funktion updateErrorDisplay überprüft auf Fehler und übersetzt und zeigt die entsprechende Fehlermeldung an, falls welche vorhanden sind.
Dynamische Übersetzungen
Mithilfe von Transloco übersetzen wir Fehlermeldungen basierend auf den Formularvalidierungsschlüsseln (z.B. required, minlength, etc.) und ihren jeweiligen Werten (z.B. Mindestanzahl von Zeichen).
DOM-Manipulation mit Renderer2
Um das DOM sicher zu manipulieren, injizieren wir Renderer2 und verwenden es, um Fehlernachrichtenelemente im Formular zu erstellen oder zu entfernen. Dies stellt sicher, dass der Code effizient bleibt und auf verschiedenen Plattformen und Umgebungen (wie serverseitiges Rendering) kompatibel ist.
Verwendung der Directive
Um die FormErrorDirective in einem Formular zu verwenden, wenden Sie sie wie folgt auf ein Formularsteuerelement an:
<form [formGroup]="form">
<label for="benutzername">Benutzername</label>
<input id="benutzername" formControlName="username">
!!-- Directive Automatisch fügt den Fehlercode an dieser Stelle ein,
wenn dieses Formularfeld einen ungültigen Zustand hat,
und ihn entfernen, wenn es wieder gültig ist. --!!
</form>
Fazit
Durch die Erstellung dieser benutzerdefinierten Directive können Sie Formularvalidierungsfehler in Angular einfach verwalten, während Sie Ihren Code modular und wartungsfreundlich halten. Die dynamische Übersetzung von Fehlermeldungen mit Transloco sorgt dafür, dass Ihre Anwendung in jeder unterstützten Sprache benutzerfreundlich ist.
