Même si la majeure partie de la validation se passe côté serveur, Angular vous permet d'ajouter une première couche de validation de formulaire côté front-end.
Vous allez utiliser les Validators pour mettre en place les champs requis du formulaire de nouveau FaceSnap, ainsi que pour vérifier que l'URL d'image entrée par l'utilisateur correspond à une URL (et non à un texte aléatoire).
Une fois les données validées, vous pourrez terminer l'implémentation de l'ajout du FaceSnap aux données de l'application pour permettre aux utilisateurs de créer leurs propres FaceSnaps !
Validez le formulaire
Ajouter une validation aux formulaires réactifs est plutôt simple : il suffit de les ajouter à la configuration des champs passés à la méthode group
de FormBuilder.
La première validation que vous allez ajouter est celle qui vérifie que les champs requis contiennent bien des valeurs. Le Validator correspondant est Validators.required
:
this.snapForm = this.formBuilder.group({
title: [null, [Validators.required]],
description: [null, [Validators.required]],
imageUrl: [null, [Validators.required]],
location: [null]
});
Pour empêcher l'utilisateur d'envoyer le formulaire s'il n'est pas valable, vous pouvez lier l'attribut disabled
du bouton d'enregistrement à l'attribut invalid
du FormGroup – si le formulaire n'est pas valable, le bouton sera désactivé.
Dans le template :
<!-- ... -->
<button type="submit" (click)="onSubmitForm()" [disabled]="snapForm.invalid">Enregistrer</button>
<!-- ... -->
Ainsi, si vous n'entrez rien dans les champs requis :
Vous allez maintenant ajouter un deuxième Validator au champ imageUrl
pour vérifier que le texte entré par l'utilisateur correspond à une URL – il s'agit de Validators.pattern
, qui compare la valeur entrée à une expression régulière (RegExp).
Déclarez une variable qui contiendra le pattern RegExp
:
// ...
snapForm!: FormGroup;
faceSnapPreview$!: Observable<FaceSnap>;
urlRegex!: RegExp;
// ...
Et dans ngOnInit()
, initialisez-la avec le pattern ci-dessous :
this.urlRegex = /(http(s)?:\/\/.)?(www\.)?[-a-zA-Z0-9@:%._+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_+.~#?&/=]*)/;
Ici vous ne vérifiez pas que l'URL est valable : simplement que le texte ressemble à une URL.
Il ne reste plus qu'à ajouter un deuxième Validator – le Validator pattern – à la configuration du contrôle imageUrl
:
this.snapForm = this.formBuilder.group({
title: [null, [Validators.required]],
description: [null, [Validators.required]],
imageUrl: [null, [Validators.required, Validators.pattern(this.urlRegex)]],
location: [null]
});
Si vous testez le formulaire de nouveau, vous verrez que le bouton Enregistrer ne s'active que si le champ URL contient quelque chose qui ressemble à une URL.
Cependant, si vous regardez la console pendant que vous entrez cette URL, vous voyez des erreurs 404 :
Est-ce que vous comprenez pourquoi ces erreurs apparaissent ?
Changez le rythme des émissions
Ces erreurs apparaissent parce que l'aperçu du FaceSnap sous le formulaire reçoit toutes les valeurs intermédiaires de l'URL, et essaie de les attribuer comme sources d'image. Du coup, tant que l'URL n'est pas complète, vous aurez des erreurs 404 ou, pire, des requêtes vers des ressources non souhaitées !
Pour éviter ces requêtes inutiles, vous pouvez modifier le déclenchement de valueChanges
du formulaire pour émettre uniquement lorsque l'utilisateur change de champ, c'est-à-dire lors du blur
des différents champs. Pour ceci, vous allez passer un objet de configuration à la méthode group
:
this.snapForm = this.formBuilder.group({
title: [null, [Validators.required]],
description: [null, [Validators.required]],
imageUrl: [null, [Validators.required, Validators.pattern(this.urlRegex)]],
location: [null]
}, {
updateOn: 'blur'
});
Maintenant, les informations entrées dans le formulaire ne sont affichées dans l'aperçu que lorsque l'utilisateur change le focus du formulaire, évitant ainsi les erreurs 404.
Ajoutez le FaceSnap
À vous de jouer !
Avec la validation mise en place, vous pouvez implémenter l'ajout du FaceSnap entré par l'utilisateur.
Vous allez créer une méthode de service qui accepte les informations du formulaire en arguments, et qui ajoutera un FaceSnap valable aux données de l'application. Vous appellerez ensuite cette méthode depuis le component, et vous redirigerez l'utilisateur vers la liste des FaceSnaps après l'enregistrement réussi.
Commencez par la méthode dans FaceSnapsService. Elle doit accepter les valeurs du formulaire, générer un FaceSnap avec les champs requis (notamment avec un Id unique et valable), et ajouter l'objet généré au tableau des FaceSnaps.
Prenez quelques instants pour l'implémenter vous-même, avant de regarder comment je m'y prends.
Suivez mon approche
Voici ma proposition :
addFaceSnap(formValue: { title: string, description: string, imageUrl: string, location?: string }) {
const faceSnap: FaceSnap = {
...formValue,
snaps: 0,
createdDate: new Date(),
id: this.faceSnaps[this.faceSnaps.length - 1].id + 1
};
this.faceSnaps.push(faceSnap);
}
Cette méthode :
accepte un objet comme argument, qui correspond à l'objet généré par le formulaire ;
crée un nouvel objet à partir de l'argument en ajoutant les champs manquants ;
ajoute 1 à l'
id
du dernier ajouté au tableau pour générer le nouveau, puisque lesid
des FaceSnap sont des entiers croissants ;ajoute le FaceSnap au tableau.
La méthode est prête à être appelée lors de l'envoi du formulaire.
La fonctionnalité souhaitée est que l'utilisateur soit redirigé après l'ajout du FaceSnap. Il faudra donc injecter FaceSnapsService et le Router dans NewFaceSnapComponent, et modifier l'implémentation de la méthode onSubmitForm()
:
// ...
constructor(private formBuilder: FormBuilder,
private faceSnapsService: FaceSnapsService,
private router: Router) { }
// ...
onSubmitForm() {
this.faceSnapsService.addFaceSnap(this.snapForm.value);
this.router.navigateByUrl('/facesnaps');
}
Avec cette dernière étape, vous avez un formulaire qui fonctionne, qui est validé, et qui ajoute bien un nouveau FaceSnap à l'application !
En résumé
Ajoutez de la validation aux contrôles de vos formulaires en passant des Validators au moment de la configuration du FormGroup.
Validators.required
rend un champ du formulaire requis.Validators.pattern
vérifie que le contenu d'un champ correspond à une expression régulière.
Qu'avons-nous appris dans cette partie du cours ?
Dans cette partie du cours, vous avez créé vos premiers formulaires.
Vous avez créé un formulaire simple sous forme de formulaire template, en utilisant le two-way binding avec
ngModel
et les références locales auxNgForm
;Vous avez implémenté un formulaire réactif avec FormBuilder et observé ses changements de valeur via son Observable
valueChanges
;Vous avez mis en place la validation avec les
Validators
et vous avez terminé l'implémentation de la création de nouveaux FaceSnaps.
Dans la prochaine partie du cours, vous apprendrez à générer et envoyer des requêtes HTTP, vous permettant de créer des applications totalement dynamiques ! Avant de découvrir tout cela, je vous invite à faire le quiz suivant – à très vite !