Introduction aux formulaires dans Angular 4: Formulaires pilotés par un modèle
French (Français) translation by honeymmmm (you can also view the original English article)



Les formulaires sont essentiels à toute application frontale moderne et sont une fonctionnalité que nous utilisons tous les jours, même si nous ne le réalisons pas. Des formulaires sont requis pour la connexion sécurisée d'un utilisateur à l'application, la recherche de tous les hôtels disponibles dans une ville donnée, la réservation d'un taxi, la création d'une liste de tâches et l'exécution de nombreuses tâches habituelles. Certains formulaires ne contiennent que quelques champs de saisie, tandis que d'autres peuvent avoir un tableau de champs qui s'étend sur deux ou trois pages.
Dans ce tutoriel, nous parlerons des différentes stratégies disponibles pour développer des formulaires dans Angular. Indépendamment de la stratégie que vous choisissez, voici ce qu’une bibliothèque de formulaires devrait couvrir:
- Prend en charge la liaison bidirectionnelle afin que les valeurs du contrôle d'entrée soient synchronisées avec l'état du composant.
- Gardez une trace de l'état du formulaire et utilisez des repères visuels pour indiquer à l'utilisateur si l'état actuel est valide ou non. Par exemple, si le nom d'utilisateur comporte des caractères non valides, une bordure rouge doit apparaître autour du champ de saisie pour le nom d'utilisateur.
- Avoir un mécanisme pour afficher correctement les erreurs de validation.
- Activer ou désactiver certaines parties du formulaire, sauf si certains critères de validation sont remplis.
Introduction aux formulaires en angulaire
Angular, étant un framework frontal complet, possède son propre ensemble de bibliothèques pour la création de formulaires complexes. La dernière version d'Angular dispose de deux stratégies puissantes de création de formulaires. Elles sont:
- formulaires pilotés par des modèles
- formes modélisées ou réactives
Les deux technologies appartiennent à la bibliothèque @angular/forms et sont basées sur les mêmes classes de contrôle de formulaire. Cependant, ils diffèrent de manière remarquable par leur philosophie, leur style de programmation et leur technique. Choisir l'un sur l'autre dépend de vos goûts personnels et de la complexité de la forme que vous essayez de créer. À mon avis, vous devriez d'abord essayer les deux approches, puis choisir celle qui correspond à votre style et au projet en cours.
La première partie du didacticiel couvrira les formulaires pilotés par un modèle avec un exemple pratique: création d'un formulaire d'inscription avec validation pour tous les champs de formulaire. Dans la deuxième partie de ce tutoriel, nous allons retracer les étapes pour créer le même formulaire en utilisant une approche pilotée par un modèle.
Formulaires pilotés par modèle
L'approche axée sur les modèles est une stratégie empruntée à l'ère AngularJS. À mon avis, c'est la méthode la plus simple pour construire des formes. Comment ça marche? Nous utiliserons des directives angulaires.
Les directives vous permettent d'attacher un comportement aux éléments du DOM.
— Angular Documentation
Angular fournit des directives spécifiques aux formulaires que vous pouvez utiliser pour lier les données d'entrée du formulaire et le modèle. Les directives spécifiques au formulaire ajoutent des fonctionnalités et un comportement supplémentaires à un formulaire HTML simple. Le résultat final est que le modèle prend en charge les valeurs de liaison avec le modèle et la validation du formulaire.
Dans ce tutoriel, nous utiliserons des formulaires basés sur des modèles pour créer la page d'inscription d'une application. Le formulaire couvrira les éléments de formulaire les plus courants et différents contrôles de validation sur ces éléments de formulaire. Voici les étapes que vous suivrez dans ce tutoriel.
- Ajoutez FormsModule à
app.module.ts. - Créez une classe pour le modèle utilisateur.
- Créez les composants initiaux et la disposition pour le formulaire d'inscription.
- Utilisez les directives de forme angulaire comme
ngModel,ngModelGroupetngForm. - Ajouter la validation à l'aide de validateurs intégrés.
- Afficher les erreurs de validation de manière significative.
- Gérer la soumission du formulaire à l'aide de
ngSubmit.
Commençons.
Conditions préalables
Le code de ce projet est disponible sur mon repo GitHub. Téléchargez le zip ou clonez le repo pour le voir en action. Si vous préférez commencer à partir de zéro, assurez-vous d'avoir installé Angular CLI. Utilisez la commande ng pour générer un nouveau projet.
1 |
$ ng new SignupFormProject |
Ensuite, générez un nouveau composant pour SignupForm.
1 |
ng generate component SignupForm |
Remplacez le contenu de app.component.html par celui-ci:
1 |
<app-signup-form> </app-signup-form> |
Voici la structure du répertoire src/. J'ai supprimé certains fichiers non essentiels pour garder les choses simples.
1 |
. |
2 |
├── app |
3 |
│ ├── app.component.css |
4 |
│ ├── app.component.html |
5 |
│ ├── app.component.ts |
6 |
│ ├── app.module.ts |
7 |
│ ├── signup-form |
8 |
│ │ ├── signup-form.component.css |
9 |
│ │ ├── signup-form.component.html |
10 |
│ │ └── signup-form.component.ts |
11 |
│ └── User.ts |
12 |
├── index.html |
13 |
├── main.ts |
14 |
├── polyfills.ts |
15 |
├── styles.css |
16 |
├── tsconfig.app.json |
17 |
└── typings.d.ts |
Comme vous pouvez le voir, un répertoire pour le composant SignupForm a été créé automatiquement. C'est là que va la plupart de notre code. J'ai également créé un nouveau User.ts pour stocker notre modèle d'utilisateur.
Le modèle HTML
Avant de nous plonger dans le modèle de composant actuel, nous devons avoir une idée abstraite de ce que nous construisons. Donc, voici la structure de forme que j'ai en tête. Le formulaire d'inscription aura plusieurs champs de saisie, un élément select et un élément checkbox.



Voici le modèle HTML que nous utiliserons pour notre page d'inscription.
Modèle HTML
1 |
<div class="row custom-row"> |
2 |
<div class= "col-sm-5 custom-container jumbotron"> |
3 |
|
4 |
<form class="form-horizontal"> |
5 |
<fieldset>
|
6 |
<legend>SignUp</legend> |
7 |
|
8 |
<!--- Email Block --->
|
9 |
<div class="form-group"> |
10 |
<label for="inputEmail">Email</label> |
11 |
<input type="text" |
12 |
id="inputEmail" |
13 |
placeholder="Email"> |
14 |
</div>
|
15 |
<!--- Password Block --->
|
16 |
<div class="form-group"> |
17 |
<label for="inputPassword">Password</label> |
18 |
<input type="password" |
19 |
id="inputPassword" |
20 |
placeholder="Password"> |
21 |
</div>
|
22 |
|
23 |
<div class="form-group"> |
24 |
<label for="confirmPassword" >Confirm Password</label> |
25 |
<input type="password" |
26 |
id="confirmPassword" |
27 |
placeholder="Password"> |
28 |
</div>
|
29 |
|
30 |
<!--- Select gender Block --->
|
31 |
<div class="form-group"> |
32 |
<label for="select">Gender</label> |
33 |
<select id="select"> |
34 |
<option>Male</option> |
35 |
<option>Female</option> |
36 |
<option>Other</option> |
37 |
</select>
|
38 |
</div>
|
39 |
|
40 |
<!--- Terms and conditions Block --->
|
41 |
<div class="form-group checkbox"> |
42 |
<label>
|
43 |
<input type="checkbox"> Confirm that you've read the Terms and |
44 |
Conditions |
45 |
</label>
|
46 |
</div>
|
47 |
|
48 |
<!--- Buttons Block --->
|
49 |
<div class="form-group"> |
50 |
<button type="reset" class="btn btn-default">Cancel</button> |
51 |
<button type="submit" class="btn btn-primary">Submit</button> |
52 |
</div>
|
53 |
</fieldset>
|
54 |
</form>
|
55 |
</div>
|
56 |
</div>
|
Les classes CSS utilisées dans le modèle HTML font partie de la bibliothèque Bootstrap utilisée pour rendre les choses belles. Comme il ne s’agit pas d’un tutoriel de conception, je ne parlerai pas beaucoup des aspects CSS du formulaire, sauf si cela est nécessaire.
Configuration de formulaire de base
Pour utiliser les directives de formulaire pilotées par un modèle, nous devons importer FormsModule à partir de @angular/forms et l'ajouter au tableau imports dans app.module.ts.
app/app.module.ts
1 |
import { FormsModule } from '@angular/forms'; |
2 |
|
3 |
@NgModule({ |
4 |
.
|
5 |
.
|
6 |
imports: [ |
7 |
BrowserModule, |
8 |
FormsModule
|
9 |
],
|
10 |
.
|
11 |
.
|
12 |
})
|
13 |
export class AppModule { } |
Ensuite, créez une classe qui contiendra toutes les propriétés de l'entité Utilisateur. Nous pouvons soit utiliser une interface et l'implémenter dans le composant, soit utiliser une classe TypeScript pour le modèle.
app/User.ts
1 |
export class User { |
2 |
|
3 |
id: number; |
4 |
email: string; |
5 |
//Both the passwords are in a single object
|
6 |
password: { |
7 |
pwd: string; |
8 |
confirmPwd: string; |
9 |
};
|
10 |
gender: string; |
11 |
terms: boolean; |
12 |
|
13 |
constructor(values: Object = {}) { |
14 |
//Constructor initialization
|
15 |
Object.assign(this, values); |
16 |
}
|
17 |
|
18 |
}
|
Maintenant, créez une instance de la classe dans le composant SignupForm. J'ai également déclaré une propriété supplémentaire pour le genre.
app/signup-form/signup-form.component.ts
1 |
import { Component, OnInit } from '@angular/core'; |
2 |
// Import the User model
|
3 |
import { User } from './../User'; |
4 |
|
5 |
@Component({ |
6 |
selector: 'app-signup-form', |
7 |
templateUrl: './signup-form.component.html', |
8 |
styleUrls: ['./signup-form.component.css'] |
9 |
})
|
10 |
export class SignupFormComponent implements OnInit { |
11 |
|
12 |
//Property for the gender
|
13 |
private gender: string[]; |
14 |
//Property for the user
|
15 |
private user:User; |
16 |
|
17 |
ngOnInit() { |
18 |
|
19 |
this.gender = ['Male', 'Female', 'Others']; |
20 |
//Create a new user object
|
21 |
this.user = new User({ |
22 |
email:"", password: { pwd: "" , confirm_pwd: ""}, |
23 |
gender: this.gender[0], terms: false}); |
24 |
}
|
25 |
|
26 |
}
|
Pour le fichier signup-form.component.html, je vais utiliser le même modèle HTML que celui décrit ci-dessus, mais avec des modifications mineures. Le formulaire d'inscription comporte un champ de sélection avec une liste d'options. Bien que cela fonctionne, nous le ferons de manière angulaire en parcourant la liste en utilisant la directive ngFor.
app / formup-form / signup-form.component.html
1 |
<div class="row custom-row"> |
2 |
<div class= "col-sm-5 custom-container jumbotron"> |
3 |
|
4 |
<form class="form-horizontal"> |
5 |
<fieldset>
|
6 |
<legend>SignUp</legend> |
7 |
. |
8 |
. |
9 |
<!--- Gender Block -->
|
10 |
<div class="form-group"> |
11 |
<label for="select">Gender</label> |
12 |
<select id="select"> |
13 |
|
14 |
<option *ngFor = "let g of gender" |
15 |
[value] = "g"> {{g}} |
16 |
</option>
|
17 |
</select>
|
18 |
</div>
|
19 |
. |
20 |
. |
21 |
</fieldset>
|
22 |
</form>
|
23 |
</div>
|
24 |
</div>
|
Ensuite, nous souhaitons lier les données de formulaire à l'objet de classe utilisateur afin que, lorsque vous entrez les données d'inscription dans le formulaire, un nouvel objet Utilisateur soit créé pour stocker ces données temporairement. De cette façon, vous pouvez garder la vue synchronisée avec le modèle, et cela s'appelle la liaison.
Il y a plusieurs façons de réaliser cela. Laissez-moi d'abord vous présenter ngModel et ngForm.
ngForm et ngModel
ngForm et ngModel sont des directives angulaires essentielles à la création de formulaires pilotés par des modèles. Commençons par ngForm en premier. Voici un extrait de ngForm des documents angulaires.
La directiveNgFormcomplète l'élémentformavec des fonctionnalités supplémentaires. Il contient les contrôles que vous avez créés pour les éléments avec une directivengModelet un attributnameet surveille leurs propriétés, y compris leur validité. Il possède également sa propre propriétévalidqui n'est vraie que si tous les contrôles contenus sont valides.
Tout d'abord, mettez à jour le formulaire avec la directive ngForm:
app/signup-form/signup-form.component.html
1 |
<form
|
2 |
class="form-horizontal" |
3 |
#signupForm = "ngForm"> |
4 |
. |
5 |
. |
6 |
</form>
|
#signupForm est une variable de référence de modèle qui fait référence à la directive ngForm qui régit la totalité du formulaire. L'exemple ci-dessous illustre l'utilisation d'un objet de référence ngForm pour la validation.
app/signup-form/signup-form.component.html
1 |
<button
|
2 |
type="submit" |
3 |
class="btn btn-success" |
4 |
[disabled]="!signupForm.form.valid"> |
5 |
Submit |
6 |
</button>
|
Ici, signupForm.form.valid renverra false sauf si tous les éléments du formulaire réussissent leurs contrôles de validation respectifs. Le bouton d'envoi sera désactivé jusqu'à ce que le formulaire soit valide.
En ce qui concerne la liaison du modèle et du modèle, il existe de nombreuses façons de procéder, et ngModel dispose de trois syntaxes différentes pour résoudre ce problème. Elles sont:
- [(ngModel)]
- [ngModel]
- ngModel
Commençons par le premier.
Liaison bidirectionnelle à l'aide de [(ngModel)]
[(ngModel)] effectue une liaison bidirectionnelle pour la lecture et l'écriture des valeurs de contrôle d'entrée. Si une directive [(ngModel)] est utilisée, le champ d'entrée prend une valeur initiale dans la classe de composant liée et la remet à jour chaque fois qu'une modification de la valeur du contrôle d'entrée est détectée (au clavier et par pression du bouton). L'image ci-dessous décrit le processus de liaison bidirectionnel mieux.



Voici le code du champ de saisie du courrier électronique:
1 |
<div class="form-group"> |
2 |
<label for="inputEmail">Email</label> |
3 |
<input type="text" |
4 |
[(ngModel)] = "user.email" |
5 |
id="inputEmail" |
6 |
name="email" |
7 |
placeholder="Email"> |
8 |
</div> |
[(ngModel)] = "user.email" lie la propriété email de l'utilisateur à la valeur d'entrée. J'ai également ajouté un attribut name et set name = "email". Ceci est important et vous obtiendrez une erreur si vous n'avez pas déclaré d'attribut name lors de l'utilisation de ngModel.
De même, ajoutez un [(ngModel)] et un attribut name unique à chaque élément de formulaire. Votre formulaire devrait ressembler à ceci maintenant:
app/signup-form/signup-form.component.html
1 |
. |
2 |
. |
3 |
. |
4 |
<div ngModelGroup="password"> |
5 |
<div class="form-group" > |
6 |
<label for="inputPassword">Password</label> |
7 |
<input type="password" |
8 |
[(ngModel)] = "user.password.pwd" name="pwd" |
9 |
placeholder="Password"> |
10 |
</div>
|
11 |
|
12 |
<div class="form-group"> |
13 |
<label for="confirmPassword" >Confirm Password</label> |
14 |
<input type="password" |
15 |
[(ngModel)] = "user.password.confirmPwd" name="confirmPwd" |
16 |
placeholder="Confirm Password"> |
17 |
</div>
|
18 |
</div>
|
19 |
<div class="form-group"> |
20 |
<label for="select">Gender</label> |
21 |
<select id="select" |
22 |
[(ngModel)] = "user.gender" name = "gender"> |
23 |
|
24 |
<option *ngFor = "let g of gender" |
25 |
[value] = "g"> {{g}} |
26 |
</option>
|
27 |
</select>
|
28 |
</div>
|
29 |
|
30 |
. |
31 |
. |
32 |
. |
Le ngModelGroup est utilisé pour regrouper des champs de formulaire similaires afin de pouvoir exécuter des validations uniquement sur ces champs de formulaire. Les deux champs de mot de passe étant liés, nous les placerons sous un seul ngModelGroup. Si tout fonctionne comme prévu, la propriété user liée au composant doit être chargée de stocker toutes les valeurs de contrôle de formulaire. Pour voir cela en action, ajoutez ce qui suit après la balise de formulaire:
1 |
{{user | json}} |
Passez la propriété utilisateur via JsonPipe pour afficher le modèle en tant que JSON dans le navigateur. Ceci est utile pour le débogage et la journalisation. Vous devriez voir une sortie JSON comme celle-ci.



Les valeurs circulent depuis la vue vers le modèle. Qu'en est-il de l'autre côté? Essayez d'initialiser l'objet utilisateur avec certaines valeurs.
app/signup-form/signup-form.component.ts
1 |
this.user = new User({ |
2 |
//initialized with some data
|
3 |
email:"thisisfromthemodel@example.com", |
4 |
password: { pwd: "" , confirm_pwd: ""}, |
5 |
gender: this.gender[0] |
6 |
|
7 |
});
|
Et ils apparaissent automatiquement dans la vue:
1 |
{ "email": "thisisfromthemodel@example.com", |
2 |
"password": { "pwd": "", "confirm_pwd": "" }, |
3 |
"gender": "Male" |
4 |
}
|
La syntaxe de liaison bidirectionnelle [(ngModel)] vous aide à créer des formulaires sans effort. Cependant, il présente certains inconvénients; il existe donc une autre approche qui utilise ngModel ou [ngModel].
Ajout de ngModel au mixage
Lorsque ngModel est utilisé, nous sommes en fait responsables de la mise à jour de la propriété du composant avec les valeurs de contrôle d'entrée et inversement. Les données d'entrée ne sont pas automatiquement transmises à la propriété utilisateur du composant.
Remplacez donc toutes les instances de [(ngModel)] = "" par ngModel. Nous conserverons l'attribut name car les trois versions de ngModel ont besoin de l'attribut name pour fonctionner.
app/signup-form/signup-form.component.html
1 |
<div class="form-group"> |
2 |
<label for="inputEmail">Email</label> |
3 |
<input type="text" |
4 |
ngModel
|
5 |
id="inputEmail" |
6 |
name="email" |
7 |
placeholder="Email"> |
8 |
</div> |
Avec ngModel, la valeur de l'attribut name deviendra une clé de l'objet de référence ngForm signupForm que nous avons créé précédemment. Ainsi, par exemple, signupForm.value.email stockera la valeur de contrôle pour l'identifiant de messagerie.
Remplacez {{user| json}} avec {{signupForm.value | json}} parce que c'est là que tout l'état est stocké en ce moment.
Liaison unidirectionnelle à l'aide de [ngModel]
Que faire si vous devez définir l'état initial à partir du composant de classe lié? C'est ce que le [ngModel] fait pour vous.



Ici, les données circulent du modèle à la vue. Apportez les modifications suivantes à la syntaxe pour utiliser la liaison unidirectionnelle:
app/signup-form/signup-form.component.html
1 |
<div class="form-group"> |
2 |
<label for="inputEmail">Email</label> |
3 |
<input type="text" |
4 |
[ngModel] = "user.email" |
5 |
id="inputEmail" |
6 |
name="email" |
7 |
placeholder="Email"> |
8 |
</div>
|
Alors, quelle approche choisir? Si vous utilisez [(ngModel)] et ngForm ensemble, vous aurez éventuellement deux états à gérer - user et signupForm.value - et cela pourrait être source de confusion.
1 |
{ "email": "thisisfromthemodel@example.com", |
2 |
"password": { "pwd": "thisispassword", "confirm_pwd": "thisispassword" }, |
3 |
"gender": "Male" |
4 |
} //user.value |
5 |
|
6 |
{ "email": "thisisfromthemodel@example.com", |
7 |
"password": { "pwd": "thisispassword", "confirm_pwd": "thisispassword" }, |
8 |
"gender": "Male" |
9 |
} //signupForm.value |
Par conséquent, je vous recommanderai plutôt d'utiliser la méthode de liaison unidirectionnelle. Mais c'est quelque chose que vous pouvez décider.
Validation et affichage des messages d'erreur
Voici nos exigences pour la validation.
- Tous les contrôles de formulaire sont requis.
- Désactivez le bouton d'envoi jusqu'à ce que tous les champs de saisie soient remplis.
- Le champ email doit contenir strictement un identifiant email.
- Le champ mot de passe doit avoir une longueur minimale de 8.
- Le mot de passe et la confirmation doivent correspondre.



Le premier est facile. Vous devez ajouter un attribut de validation required à chaque élément de formulaire comme ceci:
app/signup-form/signup-form.component.html
1 |
<input type="text" |
2 |
[ngModel] = "user.email" name="email" |
3 |
#email = "ngModel" |
4 |
placeholder="Email" |
5 |
required> |
Outre l'attribut required, j'ai également exporté une nouvelle variable de référence de modèle #email. Cela vous permet d'accéder au contrôle angulaire de la zone de saisie depuis le modèle lui-même. Nous l'utiliserons pour afficher des erreurs et des avertissements. Utilisez maintenant la propriété désactivée du bouton pour désactiver le bouton:
app/signup-form/signup-form.component.html
1 |
<button
|
2 |
type="submit" |
3 |
class="btn btn-success" |
4 |
[disabled]="!signupForm.form.valid"> |
5 |
Submit |
6 |
</button>
|
Pour ajouter une contrainte sur le courrier électronique, utilisez l'attribut pattern qui fonctionne avec les champs d'entrée. Les patterns permettent de spécifier des expressions régulières comme celle ci-dessous:
1 |
pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,3}$"
|
Pour le champ mot de passe, il suffit d'ajouter un attribut minlength="":
app/signup-form/signup-form.component.html
1 |
<input type="password" |
2 |
ngModel
|
3 |
id="inputPassword" |
4 |
name="pwd" |
5 |
#pwd = "ngModel" |
6 |
placeholder="Password" |
7 |
minlength="8" |
8 |
required> |
Pour afficher les erreurs, je vais utiliser la directive conditionnelle ngIf sur un élément div. Commençons par le champ de contrôle d'entrée pour l'email:
app/signup-form/signup-form.component.html
1 |
<div class="form-group"> |
2 |
<label for="inputEmail">Email</label> |
3 |
<input type="text" |
4 |
[ngModel] = "user.email" name="email" |
5 |
#email = "ngModel" id="inputEmail" |
6 |
placeholder="Email" |
7 |
pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,3}$" |
8 |
required> |
9 |
</div>
|
10 |
|
11 |
<!-- This is the error section -->
|
12 |
|
13 |
<div *ngIf="email.invalid && (email.dirty || email.touched)" |
14 |
class="alert alert-danger"> |
15 |
<div *ngIf = "email.errors?.required"> |
16 |
Email field can't be blank |
17 |
</div>
|
18 |
<div *ngIf = "email.errors?.pattern && email.touched"> |
19 |
The email id doesn't seem right |
20 |
</div>
|
21 |
</div>
|
Il y a beaucoup de choses ici. Commençons par la première ligne de la section d'erreur.
1 |
<div *ngIf="email.invalid && (email.dirty || email.touched)" |
2 |
class="alert alert-danger"> |
Rappelez-vous la variable #email que nous avons exportée plus tôt? Il contient une quantité d'informations sur l'état du contrôle d'entrée du champ email. Cela inclut: email.valid, email.invalid, email.dirty, email.pristine, email.touched, email.untouched et email.errors. L'image ci-dessous décrit chacune de ces propriétés en détail.



Donc, l'élément div avec le *ngIf sera rendu uniquement si l'email est invalide. Cependant, l'utilisateur sera accueilli avec des erreurs concernant les champs de saisie vides avant même qu'ils aient la possibilité de modifier le formulaire.
Pour éviter ce scénario, nous avons ajouté la deuxième condition. L'erreur sera affichée uniquement après la visite du contrôle ou la modification de la valeur du contrôle.
Les éléments div imbriqués sont utilisés pour couvrir tous les cas d’erreurs de validation. Nous utilisons email.errors pour vérifier toutes les erreurs de validation possibles, puis les afficher sous la forme de messages personnalisés. Suivez maintenant la même procédure pour les autres éléments de formulaire. Voici comment j'ai codé la validation des mots de passe.
app/signup-form/signup-form.component.html
1 |
<div ngModelGroup="password" #userPassword="ngModelGroup" required > |
2 |
<div class="form-group"> |
3 |
<label for="inputPassword">Password</label> |
4 |
<input type="password" |
5 |
ngModel name="pwd" |
6 |
id="inputPassword" placeholder="Password" |
7 |
minlength ="8" required> |
8 |
</div>
|
9 |
|
10 |
<div class="form-group"> |
11 |
<label for="confirmPassword" >Confirm Password</label> |
12 |
<input type="password" |
13 |
ngModel name="confirmPwd" |
14 |
id="confirmPassword" placeholder="Confirm Password"> |
15 |
</div>
|
16 |
|
17 |
|
18 |
<div *ngIf="(userPassword.invalid|| userPassword.value?.pwd != userPassword.value?.confirmPwd) && (userPassword.touched)" |
19 |
class="alert alert-danger"> |
20 |
|
21 |
<div *ngIf = "userPassword.invalid; else nomatch"> |
22 |
Password needs to be more than 8 characters |
23 |
</div>
|
24 |
<ng-template #nomatch > |
25 |
Passwords don't match |
26 |
</ng-template>
|
27 |
</div>
|
28 |
</div>
|
Cela commence à paraître un peu désordonné. Angular a un ensemble limité d'attributs de validateur: required, minlength, maxlength et pattern Pour couvrir tout autre scénario, comme celui de la comparaison de mots de passe, vous devrez vous baser sur les conditions ngIf imbriquées comme je l’ai fait ci-dessus. Ou idéalement, créez une fonction de validation personnalisée, que je couvrirai dans la troisième partie de cette série.
Dans le code ci-dessus, j'ai utilisé la syntaxe ngIf else introduite dans la dernière version d'Angular. Voici comment cela fonctionne:
1 |
<div *ngIf="isValid;else notvalid"> |
2 |
Valid content... |
3 |
</div>
|
4 |
|
5 |
<ng-template #notValid>Not valid content...</ng-template> |
Soumettre le formulaire en utilisant ngSubmit
Nous avons presque fini le formulaire. Maintenant, nous devons être en mesure de soumettre le formulaire, et le contrôle des données du formulaire doit être transféré à une méthode de composant, par exemple onFormSubmit ().
app/signup-form/signup-form.component.ts
1 |
<form novalidate |
2 |
(ngSubmit)="onFormSubmit(signupForm)" |
3 |
#signupForm="ngForm"> |
4 |
... |
Maintenant, pour le composant:
app/signup-form/signup-form.component.ts
1 |
...
|
2 |
public onFormSubmit({ value, valid}: { value: User, valid: boolean }) { |
3 |
this.user = value; |
4 |
console.log( this.user); |
5 |
console.log("valid: " + valid); |
6 |
}
|
7 |
...
|
Démo finale
Voici la version finale de l'application. J'ai ajouté quelques classes de bootstrap pour que le formulaire soit joli.
Résumé
Nous avons tous fini ici. Dans ce tutoriel, nous avons abordé tout ce que vous devez savoir sur la création d'un formulaire dans Angular à l'aide de l'approche basée sur des modèles. Les formulaires basés sur des modèles sont populaires pour leur simplicité et leur facilité d'utilisation.
Cependant, si vous avez besoin de créer un formulaire avec beaucoup d'éléments de formulaire, cette approche deviendra compliquée. Ainsi, dans le prochain tutoriel, nous aborderons la manière dont le modèle est conçu pour construire le même formulaire.
Partagez votre opinion dans les commentaires ci-dessous.



