Formulaires basés sur des modèles

Les formulaires sont le pilier des applications métier. Vous utilisez des formulaires pour vous connecter, soumettre une demande d'aide, passer une commande, réserver un vol, planifier une réunion et effectuer de nombreuses autres tâches de saisie de données. Lors du développement d'un formulaire, il est important de créer une expérience de saisie de données qui guide l'utilisateur de manière efficace dans le flux de travail.

Introduction aux formulaires basés sur des modèles

Développer des formulaires nécessite des compétences de conception, ainsi qu'un support de base pour la liaison de données bidirectionnelle, le suivi des modifications, la validation et la gestion des erreurs, que vous apprendrez sur cette page. Cette page vous montre comment créer un formulaire simple à partir de rien. En cours de route, vous apprendrez comment:

  • Construire une forme Angular avec un composant et un modèle.
  • ngModel permet de créer des liaisons de données bidirectionnelles pour la lecture et l'écriture de valeurs de contrôle d'entrée.
  • Suivre les changements d'état et la validité des contrôles de formulaire.
  • Fournissez un retour visuel à l'aide de classes CSS spéciales qui suivent l'état des contrôles.
  • Afficher les erreurs de validation aux utilisateurs et activer / désactiver les contrôles de formulaire.
  • Partagez des informations sur des éléments HTML à l'aide de variables de référence de modèle.
Vous pouvez créer des formulaires en écrivant des modèles à l'aide de la syntaxe Modèle Angular des directives et techniques spécifiques aux formulaires décrites dans cette page.

Vous pouvez également utiliser une approche réactive (ou basée sur un modèle) pour créer des formulaires. Cependant, cette page se concentre sur les formulaires basés sur des modèles.

Vous pouvez créer presque n'importe quel formulaire avec un modèle Angular formulaires de connexion, formulaires de contact et pratiquement tous les formulaires commerciaux. Vous pouvez disposer les contrôles de manière créative, les lier aux données, spécifier des règles de validation et afficher les erreurs de validation, activer ou désactiver de manière conditionnelle des contrôles spécifiques, déclencher un retour visuel intégré, etc...

Angular facilite le processus en effectuant de nombreuses tâches répétitives que vous auriez autrement menées à bien.
Vous apprendrez à créer un formulaire basé sur un modèle qui ressemble à ceci :



Deux des trois champs de ce formulaire sont obligatoires. Les champs obligatoires comportent une barre verte sur la gauche pour les rendre facilement repérables. Si vous supprimez le nom, le formulaire affiche une erreur de validation dans un style qui attire l'attention:



Notez que le bouton "Envoyer" est désactivé et que la barre "obligatoire" située à gauche du contrôle d'entrée passe du vert au rouge. Vous pouvez personnaliser les couleurs et l'emplacement de la barre "obligatoire" avec du CSS standard. Vous allez construire ce formulaire par petites étapes:

  • Créez la Heroclasse de modèle.
  • Créez le composant qui contrôle le formulaire.
  • Créez un modèle avec la disposition initiale du formulaire.
  • Liez les propriétés de données à chaque contrôle de formulaire à l'aide de la syntaxe ngModel de liaison de données bidirectionnelle.
  • Ajoutez un attribut name à chaque contrôle de saisie de formulaire.
  • Ajoutez des CSS personnalisés pour fournir un retour visuel.
  • Afficher et masquer les messages d'erreur de validation.
  • Gérez la soumission de formulaire avec ngSubmit.
  • Désactivez le bouton "Envoyer" du formulaire jusqu'à ce que le formulaire soit valide.

Installer

Créez un nouveau projet nommé angular-forms :

Créer la classe de modèles Hero

Lorsque les utilisateurs entrent dans les données de formulaire, vous capturez leurs modifications et mettez à jour une instance de modèle. Vous ne pouvez pas disposer le formulaire tant que vous ne saurez pas à quoi ressemble le modèle.

Un modèle peut être aussi simple qu'un ensemble de propriétés contenant des informations importantes sur une application. Voilà qui décrit bien la Heroclasse avec ses trois champs obligatoires (id, name, power) et un champ facultatif (alterEgo).

A l'aide de la commande CLI angulaire ng generate class, générez une nouvelle classe nommée Hero :

Avec ce contenu :
Le compilateur TypeScript génère un champ public pour chaque paramètre public du constructor et affecte automatiquement la valeur du paramètre à ce champ lorsque vous créez des hero.

Le alterEgo est optionnel, le constructor vous permet donc de l'omettre; notez le point d'interrogation (?) dans alterEgo?.

Vous pouvez créer un nouveau héro comme celui-ci :


Créer un composant de formulaire

Une formulaire Angular comprend deux parties: un modèle HTML et une classe de composants pour gérer les interactions de données et utilisateur par programme. Commencez par le cours, car il indique brièvement ce que l'éditeur de héros peut faire.

A l'aide de la commande CLI Angular ng generate component, générez un nouveau composant nommé HeroForm :

Avec ce contenu :

Ce composant n'a rien de spécial, rien de spécifique à la forme, rien qui le distingue des composants que vous avez écrits auparavant.

Comprendre ce composant nécessite uniquement les concepts Angular décrits dans les pages précédentes.

  • Le code importe la bibliothèque de noyau Angular et le HeroModel que vous venez de créer.
  • La valeur " app-hero-form " du sélecteur @Component signifie que vous pouvez déposer ce formulaire dans un modèle parent avec une balise ‹app-hero-form›.
  • La propriété templateUrl pointe sur un fichier séparé pour le modèle HTML.
  • Vous avez défini des données factices pour model et powers comme il convient pour une démonstration.
Ultérieurement, vous pouvez injecter un service de données pour obtenir et enregistrer des données réelles, voire exposer ces propriétés en tant qu'entrées et sorties.

Vous avez ajouté une propriété diagnostic pour renvoyer une représentation JSON du modèle. Cela vous aidera à voir ce que vous faites pendant le développement.

Réviser app.module.ts

app.module.ts définit le module racine de l'application. Vous y identifiez les modules externes que vous utiliserez dans l'application et déclarerez les composants qui appartiennent à ce module, tels que le HeroFormComponent.

Les formulaires basés sur des modèles étant dans leur propre module, vous devez ajouter le FormsModule à la matrice de imports pour le module d'application avant de pouvoir utiliser des formulaires.

Mettez-le à jour avec les éléments suivants :

Il y a deux changements :

  • Vous importez FormsModule.
  • Vous ajoutez le FormsModule à la liste de imports définie dans le décorateur @NgModule. Cela donne à l'application un accès à toutes les fonctionnalités des formulaires basés sur des modèles, y compris ngModel.
Si un composant, directive ou pipe appartient à un module dans le tableau imports, ne pas le re-déclarer dans le tableau declarations. Si vous l'avez écrit et il devrait appartenir à ce module, ne le déclarer pas dans le tableau de declarations.

Réviser app.component.html

AppComponent est le composant racine de l'application. Il va accueillir le nouveau HeroFormComponent.

Remplacez le contenu de son modèle par ce qui suit:

Il n'y a que deux changements. La template est simplement la nouvelle balise d'élément identifiée par la propriété selector du composant. Cela affiche la forme du héros lorsque le composant d'application est chargé. N'oubliez pas de supprimer également le champ name du corps de la classe.

Créer un modèle de formulaire HTML initial

Mettez à jour le fichier de modèle avec le contenu suivant :

La langue est tout simplement HTML5. Vous présentez deux des champs Hero, name et alterEgo, et les ouvrir pour l'entrée de l'utilisateur dans des boîtes d'entrée. Le contrôle ‹input› Name a l'attribut required en HTML5. Le contrôle ‹input› AlterEgo ne le fait pas car alterEgo est optionnel. Vous avez ajouté un bouton submit en bas avec quelques classes pour le style. Vous n'utilisez pas encore Angular. Il n'y a pas de liaisons ou de directives supplémentaires, juste une mise en page. Dans les formulaires basés sur des modèles, si vous avez importé FormsModule, vous n'avez rien à faire avec la balise ‹form› pour pouvoir l'utiliser FormsModule. Continuez pour voir comment cela fonctionne. Angular ne fait aucune utilisation des container, form-group, form-control et les btnclasses ou les styles d'une bibliothèque externe. Les applications Angulare peuvent utiliser n'importe quelle bibliothèque CSS ou aucune.

Pour ajouter la feuille de style, ouvrez styles.css et ajoutez la ligne d'importation suivante en haut :


Ajouter des pouvoirs avec *ngFor

Vous allez ajouter un select au formulaire et lier les options à la liste powers en utilisant ngFor.

Ajoutez le code HTML suivant immédiatement sous le groupe AlterEgo :

Ce code répète l'étiquette ‹option› pour chaque pouvoir de la liste des pouvoirs. La variable pow d'entrée modèle est une puissance différente à chaque itération; vous affichez son nom en utilisant la syntaxe d'interpolation.

Liaison de données bidirectionnelle avec ngModel

Lancer l'application maintenant serait décevant.

Vous devez maintenant afficher, écouter et extraire en même temps. Vous pouvez utiliser les techniques que vous connaissez déjà, mais vous utiliserez plutôt la nouvelle syntaxe [(ngModel)], ce qui facilite la liaison du formulaire au modèle.

Recherchez la balise ‹input› de name et mettez-la à jour comme ceci :

Vous avez ajouté une interpolation de diagnostic après la balise d'entrée pour que vous puissiez voir ce que vous faites.
Mettre l'accent sur la syntaxe de liaison: [(ngModel)]="..."
Vous avez besoin d'un autre ajout pour afficher les données. Déclarez une variable de modèle pour le formulaire. Mettez à jour la ‹form› balise avec comme suit : #heroForm="ngForm"

La variable heroForm est maintenant une référence à la directive NgForm qui régit le formulaire dans son ensemble.

La directive NgForm

La directive NgForm complète l'élément form avec des fonctionnalités supplémentaires. Il contient les contrôles que vous avez créés pour les éléments avec une directive ngModel et un attribut name et surveille leurs propriétés, y compris leur validité. Il possède également sa propre propriété valid, qui n'est vraie que si chaque contrôle contenu est valide.

Si vous exécutez l'application maintenant et commencez à taper dans la zone de saisie Name, ajouter et à supprimer des caractères, vous les verrez apparaître et disparaître du texte interpolé, à un moment donné, cela pourrait ressembler à ceci :



Le diagnostic est la preuve que les valeurs découlent réellement de la zone de saisie vers le modèle et inversement. C'est une liaison de données bidirectionnelle.

Notez que vous avez également ajouté un attribut name à la balise ‹input› et que vous l'avez défini sur "name", ce qui a du sens pour le nom du héro. Toute valeur unique fera l'affaire, mais utiliser un nom descriptif est utile. Définir un attribut name est une exigence lorsqu'on l'utilise en combinaison avec un formulaire [(ngModel)]

En interne, Angular crée des instances FormControl et les enregistre avec une directive NgForm attachée par Angular à la balise ‹form›. Chaque FormControl est enregistré sous le nom que vous avez attribué à l'attribut name.

Ajoutez des liaisons [(ngModel)] et des attributs name similaires à AlterEgo et à Power. Vous allez abandonner le message de liaison de la zone de saisie et ajouter une nouvelle liaison (en haut) à la propriété diagnostic du composant. Vous pouvez ensuite confirmer que la liaison de données bidirectionnelle fonctionne pour le modèle de héros entier.

Après révision, le noyau du formulaire devrait ressembler à ceci:

  • Chaque élément d'entrée a une propriété id utilisée par l'attribut de l'élément label pour faire correspondre l'étiquette à son contrôle d'entrée.
  • Chaque élément d'entrée possède une propriété name requise par les formulaires Angular pour enregistrer le contrôle avec le formulaire.

Si vous exécutez l'application maintenant et modifiez chaque propriété de modèle de héros, le formulaire peut s'afficher comme suit :



Le diagnostic situé en haut du formulaire confirme que toutes vos modifications sont reflétées dans le modèle. Supprimez l'interpolation {{ diagnostic }} en haut car elle a atteint son objectif.

Suivi de l'état et de la validité avec ngModel

L'utilisation ngModel dans un formulaire vous offre plus qu'une simple liaison de données bidirectionnelle. Il vous indique également si l'utilisateur a touché le contrôle, si la valeur a changé ou si la valeur est devenue invalide.

La directive NgModel ne fait pas que suivre l'état; il met à jour le contrôle avec des classes CSS Angular spéciales qui reflètent l'état. Vous pouvez utiliser ces noms de classe pour modifier l'apparence du contrôle.
Etat Classe si vrai Classe si faux
Le contrôle a été visité. ng-touched ng-untouched
La valeur du contrôle a changé. ng-dirty ng-pristine
La valeur du contrôle est valide. ng-valid ng-invalid
Ajoutez temporairement une variable de référence de modèle nommée spy à la balise name de ‹input› et utilisez-la pour afficher les classes CSS de l'entrée.
Maintenant, lancez l'application et regardez la zone de saisie name. Suivez ces étapes avec précision :

  • Regarde mais ne touche pas.
  • Cliquez dans la zone de name, puis cliquez en dehors de celle-ci.
  • Ajouter des barres obliques à la fin du nom.
  • Effacer le nom.
Les actions et effets sont les suivants :



Vous devriez voir les transitions et les noms de classe suivants:


La paire ng-valid / ng-invalid est la plus intéressante, car vous souhaitez envoyer un signal visuel fort lorsque les valeurs ne sont pas valides.

Ajouter un CSS personnalisé pour les commentaires visuels

Vous pouvez marquer les champs obligatoires et les données non valides en même temps avec une barre de couleur à gauche du champ de saisie:



Vous obtenez cet effet en ajoutant ces définitions de classe à un nouveau fichier forms.css que vous ajoutez au projet en tant que frère de index.html :

Mettez à jour le ‹head› de index.html pour inclure cette feuille de style:


Afficher et masquer les messages d'erreur de validation

Vous pouvez améliorer le formulaire. La zone de saisie Name est obligatoire et effacée, la barre devient rouge. Cela signifie que quelque chose ne va pas, mais que l'utilisateur ne sait pas ce qui ne va pas ou quoi faire. Utilisez l'état du contrôle pour révéler un message utile.

Lorsque l'utilisateur supprime le name, le formulaire doit ressembler à ceci:



Pour obtenir cet effet, étendez la balise ‹input› avec les éléments suivants :
  • Une variable de référence de modèle .
  • Le message " est requis " dans un ‹div›, que vous n'afficherez que si le contrôle est invalide.
Voici un exemple de message d'erreur ajouté à la zone de saisie du nom :

Vous avez besoin d'une variable de référence de modèle pour accéder au contrôle Angular de la zone de saisie à partir du modèle. Ici, vous avez créé une variable appelée name et lui avez donné la valeur ngModel.

Vous contrôlez la visibilité du message d'erreur de nom en liant les propriétés du contrôle name à la propriété de l'élément ‹div› de message hidden.

Dans cet exemple, vous masquez le message lorsque le contrôle est valide ou vierge; "vierge" signifie que l'utilisateur n'a pas changé la valeur depuis son affichage dans ce formulaire.

Cette expérience utilisateur est le choix du développeur. Certains développeurs souhaitent que le message soit affiché à tout moment. Si vous ignorez pristine, vous masquerez le message uniquement lorsque la valeur est valide. Si vous arrivez dans ce composant avec un nouveau hero (vierge) ou un hero invalide, le message d'erreur s'affiche immédiatement avant que vous n'ayez rien fait.

Certains développeurs souhaitent que le message ne s'affiche que lorsque l'utilisateur apporte une modification non valide. Cacher le message lorsque le contrôle est "vierge" permet d'atteindre cet objectif. Vous verrez la signification de ce choix lorsque vous ajoutez un nouveau hero au formulaire. AlterEgo est facultatif, vous pouvez donc le laisser.

La sélection du pouvoir des héros est requise. Vous pouvez ajouter le même type de traitement des erreurs à la liste ‹select› si vous le souhaitez, mais ce n'est pas impératif, car la zone de sélection limite déjà le pouvoir à des valeurs valides.

Vous allez maintenant ajouter un nouveau heros sous cette forme. Placez un bouton "New Hero" au bas de la fiche et liez son événement click à une méthode newHero() de composant.


Exécutez à nouveau l'application, cliquez sur le bouton "New Hero" et le formulaire s'efface. Les barres requises à gauche de la zone de saisie sont rouges, indiquant des propriétés non valides name et power. C'est compréhensible car ce sont des champs obligatoires. Les messages d'erreur sont masqués car le formulaire est vierge.

Entrez un nom et cliquez à nouveau sur "New Hero". L'application affiche un message d'erreur Le nom est requis. Vous ne voulez pas de messages d'erreur lorsque vous créez un nouveau héro (vide). Pourquoi en obtenez-vous une maintenant ?

L'inspection de l'élément dans les outils du navigateur révèle que la zone de saisie du nom n'est plus vierge. Le formulaire rappelle que vous avez saisi un nom avant de cliquer sur "New Hero". Le remplacement de l'objet héro n'a pas restauré l'état initial des contrôles de formulaire.

Vous devez effacer impérativement tous les indicateurs, ce que vous pouvez faire en appelant la méthode reset() du formulaire après avoir appelé la méthode newHero().

Cliquez maintenant sur "Nouveau héros" pour réinitialiser le formulaire et ses indicateurs de contrôle.

Envoyez le formulaire avec ngSubmit

L'utilisateur doit pouvoir soumettre ce formulaire après l'avoir rempli. Le bouton "submit" situé au bas du formulaire ne fait rien, mais déclenche l'envoi d'un formulaire en raison de son type ( type="submit" ).

Une "soumission de formulaire" est inutile pour le moment. Pour le rendre utile, liez la propriété ngSubmit du formulaire à la méthode onSubmit() du composant de formulaire hero :

Vous aviez déjà défini une variable de référence de modèle #heroForm et l'aviez initialisée avec la valeur " ngForm ". Maintenant, utilisez cette variable pour accéder au formulaire avec le bouton "submit".

Vous lierez la validité globale du formulaire via la variable heroForm de la propriété disabled du bouton à l'aide d'une liaison d'événement. Voici le code :

Si vous exécutez l'application maintenant, vous constaterez que le bouton est activé, bien qu'il ne fasse encore rien d'utile.

Maintenant, si vous supprimez le nom, vous ne respectez pas la règle "obligatoire", qui est dûment notée dans le message d'erreur. Le bouton "Soumettre" est également désactivé.

Pas impressionné ? Pensez-y un instant. Que feriez-vous pour relier l'état d'activation / désactivation du bouton à la validité du formulaire sans l'aide d'Angular ?

Pour vous, c'était aussi simple que cela:
  • Définissez une variable de référence de modèle sur l'élément de formulaire (amélioré).
  • Reportez-vous à cette variable dans un bouton à plusieurs lignes.

Basculer entre deux régions de formulaire (crédit supplémentaire)

Pour un effet visuel plus frappant, masquez la zone de saisie des données et affichez autre chose.
Envelopper le formulaire dans un ‹div› et lier sa propriété hidden à la propriété HeroFormComponent.submitted.

Le formulaire principal est visible depuis le début, car la propriété submitted est false jusqu'à ce que vous le soumettiez.

Lorsque vous cliquez sur le bouton "Submit", l'indicateur submitted devient true et le formulaire disparaît comme prévu.

L'application doit maintenant afficher quelque chose d'autre pendant que le formulaire est à l'état soumis. Ajoutez le code HTML suivant sous le ‹div› wrapper que vous venez d'écrire :

Il y a encore le hero, affiché en lecture seule avec des liaisons d'interpolation. Cela ‹div› n'apparaît que lorsque le composant est à l'état soumis. Le code HTML comprend un bouton "Modifier" dont l'événement click est lié à une expression qui supprime l'indicateur submitted. Lorsque vous cliquez sur le bouton "Modifier", ce bloc disparaît et le formulaire modifiable réapparaît.

Résumé

Le formulaire Angular décrite dans cette page tire parti des fonctionnalités suivantes de la structure pour prendre en charge la modification, la validation des données, etc... :

  • Un modèle de formulaire HTML Angular.
  • Une classe de composants de formulaire avec un décorateur @Component.
  • Traitement de la soumission de formulaire en se liant à la propriété event NgForm.ngSubmit.
  • Variables de référence de modèle telles que #heroForm et #name.
  • [(ngModel)] syntaxe pour la liaison de données bidirectionnelle.
  • Utilisation d'attributs name pour la validation et le suivi des modifications d'éléments de formulaire.
  • Propriété valide de la variable de référence sur les contrôles d'entrée pour vérifier si un contrôle est valide et afficher / masquer les messages d'erreur.
  • Contrôler l'état activé du bouton "submit" en le liant à la validité NgForm.
  • Classes CSS personnalisées fournissant aux utilisateurs un retour visuel sur les contrôles non valides.