Introduction aux formulaires avec Angular

La gestion des entrées utilisateur avec des formulaires est la pierre angulaire de nombreuses applications. Les applications utilisent des formulaires pour permettre aux utilisateurs de se connecter, de mettre à jour un profil, de saisir des informations sensibles et d'effectuer de nombreuses autres tâches de saisie de données.

Angular propose deux approches différentes pour gérer les entrées utilisateur via des formulaires: réactif et basé sur des modèles. Les deux permettent de capturer les événements d'entrée utilisateur à partir de la vue, de valider la saisie utilisateur, de créer un modèle de formulaire et un modèle de données à mettre à jour et de fournir un moyen de suivre les modifications.

Les formulaires réactifs et basés sur des modèles traitent et gèrent les données de formulaire différemment. Chacun offre des avantages différents.
  • Les formulaires réactifs sont plus robustes : ils sont plus évolutifs, réutilisables et testables. Si les formulaires constituent un élément clé de votre application ou si vous utilisez déjà des modèles réactifs pour générer votre application, utilisez des formulaires réactifs.
  • Les formulaires basés sur des modèles sont utiles pour ajouter un formulaire simple à une application, tel qu'un formulaire d'inscription à une liste de courrier électronique. Ils sont faciles à ajouter à une application, mais ils ne sont pas aussi évolutifs que les formulaires réactifs.
Ce guide fournit des informations pour vous aider à choisir le type de formulaire le mieux adapté à votre situation. Il présente les blocs de construction communs utilisés par les deux approches. Il résume également les principales différences entre les deux approches et illustre ces différences dans le contexte de la configuration, du flux de données et des tests.


Les principales différences

Le tableau ci-dessous récapitule les principales différences entre les formulaires réactifs et basés sur des modèles.

Formulaires réactifs Formulaires basés sur des modèles
Configuration (modèle de formulaire) Plus explicite, créé dans la classe de composant Moins explicite, créé par des directives
Modèle de données Structuré Non structuré
Prévisibilité Synchrone Asynchrone
Form validation Les fonctions Directives
Mutabilité Immuable Mutable
L'évolutivité Accès à l'API de bas niveau Abstraction au-dessus des API

Fondation commune

Les formulaires réactifs et les formulaires basés sur des modèles partagent les blocs de construction sous-jacents.

  • FormControl suit la valeur et l'état de validation d'un contrôle de formulaire individuel.
  • FormGroup suit les mêmes valeurs et statut pour une collection de contrôles de formulaire.
  • FormArray suit les mêmes valeurs et le même statut pour un tableau de contrôles de formulaire.
  • ControlValueAccessor crée un pont entre les instances FormControl Angular et les éléments natifs du DOM.

Configuration du modèle de formulaire

Les formulaires réactifs et basés sur des modèles utilisent tous deux un modèle de formulaire pour suivre les modifications de valeur entre les formulaires Angular et les éléments de saisie de formulaire. Les exemples ci-dessous montrent comment le modèle de formulaire est défini et créé.

Configuration "forme réactive"

Voici un composant avec un champ de saisie pour un contrôle unique implémenté à l'aide de formulaires réactifs.

La source fournit la valeur et le statut de l'élément de formulaire à un moment donné. Dans les formes réactives, le modèle de forme est la source. Dans l'exemple ci-dessus, le modèle de formulaire est l'instance de FormControl.


Avec les formulaires réactifs, le modèle de formulaire est explicitement défini dans la classe de composants. La directive de formulaire réactif (dans ce cas FormControlDirective) relie ensuite l'instance FormControl existante à un élément de formulaire spécifique dans la vue à l'aide d'un accessor de valeur (ControlValueAccessor).

Configuration "forme basés sur les modèles"

Voici le même composant avec un champ de saisie pour un contrôle unique implémenté à l'aide de formulaires basés sur le modèle.

Dans les formulaires basés sur des modèles, la source de la vérité est le modèle.



L'abstraction du modèle de formulaire favorise la simplicité par rapport à la structure. La directive de formulaire gérée par le modèle NgModel est responsable de la création et de la gestion de l'instance FormControl pour un élément de formulaire donné. C'est moins explicite, mais vous n'avez plus de contrôle direct sur le modèle de formulaire.

Flux de données dans les formulaires

Lors de la création de formulaires dans Angular, il est important de comprendre comment le framework traite les données provenant de l'utilisateur ou de modifications programmatiques. Les formulaires réactifs et les formulaires basés sur des modèles suivent deux stratégies différentes lors de la saisie d'un formulaire. Les exemples de flux de données ci-dessous commencent par l'exemple de champ de saisie de couleur préféré, puis montrent comment les modifications apportées à la couleur préférée sont gérées dans des formulaires réactifs par rapport aux formulaires gérés par des modèles.

Flux de données "forme réactive"

Comme décrit ci-dessus, dans les formulaires réactifs, chaque élément de formulaire dans la vue est directement lié à un modèle de formulaire, instance de FormControl. Les mises à jour de la vue vers le modèle et du modèle vers la vue sont synchrones.

Les diagrammes ci-dessous utilisent le même exemple de couleur favorite pour montrer comment les données circulent lorsque la valeur d'un champ d'entrée est modifiée à partir de la vue, puis à partir du modèle.


Les étapes ci-dessous décrivent le flux de données d'une vue à un modèle.

  • L'utilisateur tape une valeur dans l'élément d'entrée, dans ce cas, la couleur favorite Blue.
  • L'élément de saisie de formulaire émet un événement "input" avec la dernière valeur.
  • L'accesseur de valeur de contrôle à l'écoute des événements sur l'élément de saisie du formulaire relaie immédiatement la nouvelle valeur à l'instance FormControl.
  • L'instance FormControl émet la nouvelle valeur à travers l'observable valueChanges.
  • Tous les abonnés à l'observable valueChanges reçoivent la nouvelle valeur.



Les étapes ci-dessous décrivent le flux de données du modèle à le vue.

  • L'utilisateur appelle la méthode favoriteColorControl.setValue(), qui met à jour la valeur du FormControl.
  • L'instance FormControl émet la nouvelle valeur à travers l'observable valueChanges.
  • Tous les abonnés à l'observable valueChanges reçoivent la nouvelle valeur.
  • L'accesseur de valeur de contrôle sur l'élément d'entrée du formulaire met à jour l'élément avec la nouvelle valeur.

Flux de données "forme basés sur des modèles"

Dans les formulaires gérés par des modèles, chaque élément de formulaire est lié à une directive qui gère le modèle de formulaire en interne.

Les diagrammes ci-dessous utilisent le même exemple de couleur favorite pour montrer comment les données circulent lorsque la valeur d'un champ d'entrée est modifiée à partir de la vue, puis à partir du modèle.



Les étapes ci-dessous décrivent le flux de données d'une vue à l'autre lorsque la valeur d'entrée change du rouge au bleu .

  • L'utilisateur tape Blue dans l'élément input.
  • L'élément input émet un événement "input" avec la valeur Blue.
  • L'accesseur de valeur de contrôle attaché à l'entrée déclenche la méthode setValue() sur l'instance FormControl.
  • L'instance FormControl émet la nouvelle valeur à travers l'observable valueChanges.
  • Tous les abonnés à l'observable valueChanges reçoivent la nouvelle valeur.
  • L'accesseur de valeur de contrôle appelle également la méthode NgModel.viewToModelUpdate() qui émet un événement ngModelChange.
  • Étant donné que le modèle utilise une liaison de données bidirectionnelle pour la propriété favoriteColor, celle-ci est mise à jour avec la valeur émise par l'événement ngModelChange(bleu).



Les étapes ci-dessous décrivent le flux de données du modèle à afficher lorsque la modification favoriteColor passent du bleu au rouge.

  • La valeur favoriteColor est mise à jour dans le composant.
  • La détection de changement commence.
  • Lors de la détection des modifications, le ngOnChanges() de cycle de vie est appelé sur l'instance NgModel de directive, car la valeur de l'une de ses entrées a été modifiée.
  • La méthode ngOnChanges() met en file d'attente une tâche asynchrone pour définir la valeur de l'interne FormControl.
  • La détection de changement est terminée.
  • La tâche pour définir la valeur est exécutée.
  • L'instance FormControl émet la dernière valeur à travers l'observable valueChanges.
  • Tous les abonnés à l'observable valueChanges reçoivent la nouvelle valeur.
  • L'accesseur de valeur de contrôle met à jour l'élément de saisie de formulaire dans la vue avec la dernière valeur favoriteColor.

Validation de formulaire

La validation fait partie intégrante de la gestion de tout ensemble d'un formulaire. Que vous vérifiiez la présence de champs obligatoires ou interrogiez une API externe pour un nom d'utilisateur existant, Angular fournit un ensemble de validateurs intégrés ainsi que la possibilité de créer des validateurs personnalisés.

  • Les formulaires réactifs définissent les validateurs personnalisés comme des fonctions qui reçoivent un contrôle à valider.
  • Les formulaires basés sur des modèles sont liés à des directives de modèle et doivent fournir des directives de validation personnalisées qui encapsulent les fonctions de validation.

Testing

Le test joue un rôle important dans les applications complexes et une stratégie de test plus simple est utile pour vérifier que vos formulaires fonctionnent correctement. Les formulaires réactifs et les formulaires basés sur des modèles ont différents niveaux de confiance dans le rendu de l'interface utilisateur pour effectuer des assertions basées sur le contrôle de formulaire et les modifications de champ de formulaire. Les exemples suivants illustrent le processus de test de formulaires avec des formulaires réactifs et basés sur des modèles.

Test de "forme réactive"

Les formulaires réactifs constituent une stratégie de test relativement simple, car ils fournissent un accès synchrone au formulaire et aux modèles de données. Ils peuvent également être testés sans restitution de l'interface utilisateur. Dans ces tests, l'état et les données sont interrogés et manipulés par le contrôle sans interagir avec le cycle de détection de changement.

Les tests suivants utilisent les composants de couleur préférés mentionnés précédemment pour vérifier les flux de données d'une vue à l'autre et d'un modèle à afficher pour un formulaire réactif.

Le test suivant vérifie le flux de données d'une vue à l'autre.

Voici les étapes effectuées dans la vue pour modéliser le test.

  • Interrogez la vue sur l'élément d'entrée du formulaire et créez un événement "entrée" personnalisé pour le test.
  • Définissez la nouvelle valeur pour l'entrée sur Rouge et envoyez l'événement "input" sur l'élément de saisie du formulaire.
  • Vérifiez que la valeur favoriteColorControl du composant correspond à la valeur de l'entrée.

Le test suivant vérifie le flux de données du modèle à afficher.

Voici les étapes effectuées dans le modèle pour afficher le test.

  • Utilisez favoriteColorControl, une instance FormControl pour définir la nouvelle valeur.
  • Interrogez la vue pour l'élément d'entrée de formulaire.
  • Vérifiez que la nouvelle valeur définie sur le contrôle correspond à la valeur de l'entrée.

Test de "forme basés sur des modèles"

L'écriture de tests avec des formulaires basés sur des modèles nécessite une connaissance détaillée du processus de détection des modifications et une compréhension du mode d'exécution des directives à chaque cycle, afin de garantir que les éléments sont interrogés, testés ou modifiés au bon moment.

Les tests suivants utilisent les composants de couleur préférés mentionnés précédemment pour vérifier les flux de données d'une vue à l'autre et d'un modèle à afficher pour un formulaire basé sur un modèle.

Le test suivant vérifie le flux de données d'une vue à l'autre.

Voici les étapes effectuées dans la vue pour modéliser le test.

  • Interrogez la vue sur l'élément d'entrée du formulaire et créez un événement "entrée" personnalisé pour le test.
  • Définissez la nouvelle valeur pour l'entrée sur Rouge et envoyez l'événement "input" sur l'élément de saisie du formulaire.
  • Exécutez la détection de changement à travers le dispositif de test.
  • Vérifiez que la valeur favoriteColor de la propriété du composant correspond à la valeur de l'entrée.

Le test suivant vérifie le flux de données du modèle à afficher.

Voici les étapes effectuées dans le modèle pour afficher le test.

  • Utilisez l'instance de composant pour définir la valeur de la propriété favoriteColor.
  • Exécutez la détection de changement à travers le dispositif de test.
  • Utilisez la méthode tick() pour simuler le passage du temps dans la tâche fakeAsync().
  • Interrogez la vue pour l'élément d'entrée de formulaire.
  • Vérifiez que la valeur d'entrée correspond à la valeur de la propriété favoriteColor dans l'occurrence du composant.

Mutabilité

La méthode de suivi des modifications joue un rôle dans l'efficacité de votre application.

  • Les formulaires réactifs préservent la pureté du modèle de données en lui fournissant une structure de données immuable. Chaque fois qu'une modification est déclenchée sur le modèle de données, l'instance FormControl renvoie un nouveau modèle de données plutôt que de mettre à jour le modèle de données existant. Cela vous donne la possibilité de suivre les modifications uniques apportées au modèle de données via l'observable du contrôle. Cela offre un moyen d'améliorer l'efficacité de la détection des modifications, car elle n'a besoin que de mettre à jour les modifications uniques. Elle suit également des modèles réactifs s'intégrant avec des opérateurs observables pour transformer les données.
  • Les formulaires basés sur des modèles reposent sur la mutabilité avec une liaison de données bidirectionnelle pour mettre à jour le modèle de données dans le composant à mesure que des modifications sont apportées dans le modèle. Comme il n'y a pas de modifications uniques à suivre sur le modèle de données lors de l'utilisation de la liaison de données bidirectionnelle, la détection des modifications est moins efficace pour déterminer le moment où des mises à jour sont nécessaires.

La différence est démontrée dans les exemples ci-dessus en utilisant l'élément d'entrée de couleur préféré.

  • Avec les formulaires réactifs, l'instance FormControl renvoie toujours une nouvelle valeur lorsque la valeur du contrôle est mise à jour.
  • Avec les formulaires basés sur des modèles, la propriété de couleur favorite est toujours modifiée sur sa nouvelle valeur.

L'évolutivité

Si les formulaires constituent un élément central de votre application, l'évolutivité est très importante. Il est essentiel de pouvoir réutiliser des modèles de formulaire pour tous les composants.

  • Les formulaires réactifs fournissent un accès aux API de bas niveau et un accès synchrone au modèle de formulaire, facilitant ainsi la création de formulaires à grande échelle.
  • Les formulaires basés sur des modèles se concentrent sur des scénarios simples, ne sont pas aussi réutilisables, résument les API de bas niveau et fournissent un accès asynchrone au modèle de formulaire. L'abstraction avec des formulaires basés sur des modèles apparaît également dans les tests, testant des formulaires réactifs nécessitant moins de configuration et ne dépendant pas du cycle de détection des modifications lors de la mise à jour et de la validation du modèle de formulaire et des modèles de données au cours des tests.

Dernières pensées

Le choix d'une stratégie commence par la compréhension des forces et des faiblesses des options présentées. L'accès aux API de bas niveau et aux modèles de formulaire, la prévisibilité, la mutabilité, des stratégies de validation et de test simples et l'évolutivité sont des considérations importantes dans le choix de l'infrastructure que vous utilisez pour créer vos formulaires dans Angular. Les formulaires basés sur des modèles sont similaires aux modèles dans AngularJS, mais ils ont des limites en raison des critères de nombreuses applications Angular à grande échelle modernes. Les formes réactives minimisent ces limitations. Les formes réactives s'intègrent aux schémas réactifs déjà présents dans d'autres domaines de l'architecture Angular et complètent bien ces exigences.