17-4 Validations
On peut créer un formulaire, renseigner les champs, le soumettre et lire les données, mais un formulaire vient généralement avec des validations. En effet, avant de créer un projet, on veut s'assurer qu'il a au minimum un nom et une description.
Valider un champ
Pour valider un champ de formulaire, on doit premièrement définir une ou plusieurs règles de validation. Il existe plusieurs règles prédéfinies dans Angular
et vous pouvez consulter la liste complète ici: https://angular.io/api/forms/Validators.
Il est évidemment possible de créer nos propres valideurs, mais ceux par défaut seront suffisants pour commencer.
Validator Required
pour spécifier qu'un champ est requis
Le valideur le plus évident est Required
, comme quoi un champ est requis. Pour ajouter un valideur, on passe un deuxième argument à FormControl()
, soit un tableau contenant la liste des valideurs (et donc des validations à exécuter).
export class ProjetCreer {
projetForm = new FormGroup({
nom: new FormControl('', [Validators.required]),
description: new FormControl(''),
});
//...
Validator minLength
Pour le nom du projet, au delà de vérifier que des données ont été entrées, on pourrait fournir une longueur minimale comme 3 caractères.
export class ProjetCreer {
projetForm = new FormGroup({
nom: new FormControl('', [Validators.required, Validators.minLength(3)]),
description: new FormControl(''),
});
//...
Le fait de mettre des valideurs n'empêche pas de soumettre le formulaire, mais nous permets de vérifier si le formulaire est valide ou non avant d'en faire l'envoi, ou encore d'afficher des messages à l'utilisateur.
Nous verrons un peu plus loin comment traiter la soumission du formulaire.
Afficher les erreurs de validation
Utilisation de getters pour les champs
Pour accéder aux champs à partir du template, il faut accéder au formulaire. Pour cela, on peut faire des getters/setters, ce qui simplifiera grandement l'accès aux valeurs derrière les champs.
Ajoutez les getters/setters suivants pour rendre disponibles au template les champs de formulaire:
export class ProjetCreer {
projetForm = new FormGroup({
nom: new FormControl(''),
description: new FormControl(''),
});
get nom() {
return this.projetForm.get('nom');
}
get description() {
return this.projetForm.get('description')
}
protected soumettre() {
let nom = this.nom?.value;
console.log(nom);
}
}
Afficher les erreurs
Pour afficher un message d'erreur, on peut utiliser un div
avec la classe invalid-feedback
. En effet, cette classe CSS applique un style de message d'erreur au texte. Il s'agit d'une classe propre à Bootstrap et il est important de la mettre après le champ/label.
@Component({
selector: 'app-projet-creer',
imports: [
ReactiveFormsModule
],
template: `
<div class="row">
<div class="col-lg-6 offset-lg-3">
<h1>Créer un nouveau projet</h1>
<form [formGroup]="projetForm" (ngSubmit)="soumettre()">
<div class="form-floating mb-3">
<input type="text" formControlName="nom" class="form-control" id="projetNom" placeholder="Nom">
<label for="projetNom">Nom</label>
<div class="invalid-feedback">
@if(nom?.errors?.['required']) {
<span>
Veuillez entrer un nom pour le projet
</span>
}
</div>
</div>
<div class="form-floating mb-3">
<textarea class="form-control" formControlName="description" placeholder="Description" id="projetDescription"></textarea>
<label for="projetDescription">Description</label>
</div>
<button type="submit" class="btn btn-primary">Soumettre</button>
</form>
</div>
</div>
`,
styles: ``
})
@if("nom?.errors?.['required']")
affiche conditionnellement le message, tout dépendant de si le champ nom
contient une erreur de type required
.
Classe CSS is-invalid
Malheureusement, cela n'affiche toujours pas de message. La raison est que le bloc invalid-feedback
est seulement affiché dans le cas où la classe CSS is-invalid
est présente sur le champ. Encore là, il s'agit d'une mécanique propre à Bootstrap.
On peut ajouter de façon conditionnelle cette classe au niveau du champ de la façon suivante:
@Component({
selector: 'app-projet-creer',
imports: [
ReactiveFormsModule
],
template: `
<div class="row">
<div class="col-lg-6 offset-lg-3">
<h1>Créer un nouveau projet</h1>
<form [formGroup]="projetForm" (ngSubmit)="soumettre()">
<div class="form-floating mb-3">
<input type="text" formControlName="nom"
class="form-control"
id="projetNom" placeholder="Nom"
[class.is-invalid]="nom?.invalid">
<label for="projetNom">Nom</label>
<div class="invalid-feedback">
@if(nom?.errors?.['required']) {
<span>
Veuillez entrer un nom pour le projet
</span>
}
</div>
</div>
<div class="form-floating mb-3">
<textarea class="form-control" formControlName="description" placeholder="Description" id="projetDescription"></textarea>
<label for="projetDescription">Description</label>
</div>
<button type="submit" class="btn btn-primary">Soumettre</button>
</form>
</div>
</div>
`,
styles: ``
})
[class.is-invalid]
est une directive Angular permettant d'ajouter ou non une classe (is-invalid
ici), tout dépendant d'une condition, soit la portion de droite de l'expression.[class.is-invalid]="nom?.invalid"
applique la classe CSSis-invalid
si la propriéténom
est invalide.
Maintenant, le message s'affiche!

Afficher le message d'erreur suite à l'entrée de données
Le message est constamment affiché, même si vous n'avez pas encore touché au formulaire. C'est un peu étrange qu'un formulaire vous soit présenté en mode erreur avant même que vous ayez interagi avec ce dernier.
Pour pallier à ce problème, on peut modifier la condition d'affichage de la classe CSS is-invalid
pour inclure deux conditions supplémentaires:
<input type="text" formControlName="nom"
class="form-control"
id="projetNom" placeholder="Nom"
[class.is-invalid]="nom?.invalid && (nom?.dirty || nom?.touched)">
WebStorm affichera en rouge la propriété touched
, mais c'est un bogue de WebStorm. Vous pouvez ignorer, l'application compile et s'exécute correctement.
dirty
veut dire que le champ a été modifié.
touched
veut dire que l'utilisateur a interagi avec le champ.
De cette façon, on présente l'erreur seulement si l'utilisateur a interagi avec le champ ou que ce dernier a été modifié d'une quelconque façon.
Afficher plus d'un message d'erreur
Le champ nom contient deux valideurs: required
et minlength
. Pour afficher plus d'un message, on n'a qu'à ajouter une condition supplémentaire dans la liste des messages d'erreur invalid-feedback
via l'utilisation de @if
.
<!-- ... -->
<div class="form-floating mb-3">
<input type="text" formControlName="nom"
class="form-control"
id="projetNom" placeholder="Nom"
[class.is-invalid]="nom?.invalid && (nom?.dirty || nom?.touched)">
<label for="projetNom">Nom</label>
<div class="invalid-feedback">
@if(nom?.errors?.['required']) {
<span>
Veuillez entrer un nom pour le projet
</span>
}
@if(nom?.errors?.['minlength']) {
<span>
Le nom du projet doit contenir au minimum 3 caractères
</span>
}
</div>
</div>
<!-- ... -->
Un seul message d'erreur sera affiché à la fois! Ainsi, pour voir le message de longueur minimale, vous devrez entrer 1 ou 2 caractères.
Validation OnSubmit
Il est possible de passer un objet d'options au FormGroup
et cet objet peut contenir une propriété updateOn
qui précise à quel moment la validation doit avoir lieu.
Pour le moment, la validation a lieu dès que vous commencez à entrer des données dans le champ. Cela peut être agaçant pour un utilisateur de recevoir des messages d'erreur immédiatement alors qu'il n'a pas fini de renseigner le champ.
Il est donc possible de valider le formulaire lors de trois événements distincts:
change
(par défaut)blur
lorsque l'utilisateur quitte le champsubmit
lorsque le formulaire est envoyé
Essayons de changer pour blur
:
export class ProjetCreer {
projetForm = new FormGroup({
nom: new FormControl('', [Validators.required, Validators.minLength(3)]),
description: new FormControl(''),
}, {
updateOn : 'blur'
});
Observez dans le navigateur que les erreurs du champ nom
sont maintenant seulement affichées lorsque vous quittez le champ nom
!
Nous allons laisser le tout ainsi.