Faire des formulaires réutilisables avec Angular
Table des matières
Contexte
Dans les grosses applications avec beaucoup de pages et de formulaires, il est parfois nécessaire d'avoir des champs ou des groups de champs réutilisables dans différentes pages.
Par exemple, pour la création et l'édition d'une même entité, nous serions tentés de n'avoir qu'un seul formulaire pour les deux pages. Nous allons voir comment réaliser cela.
Création du composant de formulaire
import { Component, forwardRef } from '@angular/core';
import { ControlValueAccessor, FormControl, FormGroup, NG_VALIDATORS, NG_VALUE_ACCESSOR, Validator, Validators } from '@angular/forms';
@Component({
selector: 'app-user-form',
template: `
<form [formGroup]="form">
<label>FirstName: <input formControlName="firstname" /></label>
<label>LastName: <input formControlName="lastname" /></label>
</form>
`,
providers: [
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => UserFormComponent), multi: true },
{ provide: NG_VALIDATORS, useExisting: forwardRef(() => UserFormComponent), multi: true }
]
})
export class UserFormComponent implements ControlValueAccessor, Validator {
public form = new FormGroup({
firstname: new FormControl('', [Validators.required]),
lastname: new FormControl('', [Validators.required]),
});
public registerOnChange(fn: (value: any) => {}) {
this.form.valueChanges.subscribe(fn);
}
public writeValue(value: any) {
if (value) {
this.form.patchValue(value);
} else {
this.form.reset();
}
}
public registerOnTouched(_: () => {}) {}
public validate(_: FormControl) {
return this.form.valid ? null : { user: { valid: false } };
}
}
En implémentant ControlValueAccessor
et Validator
, nous allons devoir implémenter des méthodes qui vont permettre au reactive form d'Angular de communiquer les valeurs et l'état de notre formulaire au formulaire parent.
Le composant app-user-form
pourra donc s'utiliser comme un simple champs de formulaire, sauf qu'il s'agira d'un groupe de champs.
Utilisation dans une page
Par exemple, si nous voulons utiliser notre formulaire dans une page UserCreateComponent
, nous devrons juste passer l'instance de notre formulaire à l'élément app-user-form
, et ce dernier se chargera du reste.
import { Component } from '@angular/core';
import { FormControl } from '@angular/forms';
@Component({
selector: 'app-user-create',
template: `
<app-user-form [formControl]="form"></app-user-form>
<button [disabled]="form.invalid" (click)="submit()">Submit</button>
`
})
export class UserCreateComponent {
public form = new FormControl();
public submit(): void {
console.log(this.form.value);
}
}