Formulaires modaux avec Vue.JS et Vuetify

Formulaires modaux avec Vue.JS et Vuetify

Les challenges du développement front-end sont nombreux et variés, et ils requierent de toujours faire preuve de créativité pour trouver les solutions adaptées.
Parmi ceux-ci, certains sont récurrents, on pense par exemple à la création d’interfaces d’administration. Pour cela on utilise souvent des formulaires, et s’il est tout à fait possible de leur dédier une page chacun, il peut être appréciable de les afficher sur la même page : dans ce cas on pourrait choisir de les faire apparaître dans des pop-ups.

De plus en plus d’outils sont disponibles pour les développeurs front et facilitent déjà ce travail.
Dans cet exemple nous allons utiliser VueJS et son router client vue-router, couplé à Vuetify pour l’apparence graphique.
Vuetify est une bibliothèque de composants graphiques material design. On l’utilisera ici pour simplifier l’aspect design mais il est tout à fait possible de lui préférer une autre librairie ou de choisir sa propre solution.
Il n’est pas nécessaire de la connaître pour la suite de la lecture.

Objectifs fonctionnels

On veut donc lister plusieurs items d’une ressource, pourquoi pas quelques fruits, tout en détaillant leurs attributs. On souhaite donc avoir pour chaque fruit un nom, une description et une image. Pour simplifier cet exemple on va se contenter de stocker une url pour afficher nos images.

La donnée par défaut de notre application va donc ressembler à ceci.
On peut en déduire le template suivant :

Ici j’ai choisi de représenter la liste sous forme de cartes, mais on
pourrait imaginer la même approche avec tout autre forme de
représentation.

J’ai également ajouté des boutons d’ajout, de modification et de suppression de fruits. En effet, on souhaite pouvoir ajouter des items à notre liste, en retirer ou modifier les propriétés de chacun d’eux.
Pour cela on va avoir besoin d’un formulaire de création, un autre de modification, et un dernier de suppression.

Les formulaires de création et modification sont sensiblement identiques, celui d’update étant juste pré-rempli avec les données de l’item sélectionné.
Le formulaire de suppression est plus simple, il faudra juste afficher une fenêtre de confirmation avant l’action.

Le formulaire d’édition

La pop-up de confirmation de suppression

Approche technique directe

Le composant v-dialog de vuetify affiche une modale en fonction de la valeur de la variable associée à son v-model, ce qui est très utile pour ce que l’on cherche à faire. Immédiatement, on pourrait envisager d’avoir plusieurs v-dialog, qui s’afficheront conditionnellement pour contenir nos formulaires.

Puisque les formulaires de modification et de création contiennent les même champs, on peut les factoriser et n’avoir que 2 v-dialog qui s’affichent selon les actions de l’utilisateur.

Cette figure montre le code du composant formulaire, avec un champ pour chaque propriété de notre ressource, et deux boutons émettant des événements de soumission ou d’annulation de ce formulaire.

Une maintenance verbeuse et complexe

Cette solution est-elle satisfaisante ? Non, d’abord les formulaires d’édition et de création peuvent changer, selon si l’on a des items de plusieurs types, des valeurs par défaut à gérer à la création, ou des contraintes à la modification. Ensuite si l’on voulait afficher un autre formulaire, par exemple pour une ressource annexe, il faudrait ajouter autant de v-dialog que de formulaires et on risque de congestionner le template et de complexifier le composant en lui attribuant la responsabilité de la logique d’affichage des fenêtres et du formatage des données.

On comprend rapidement qu’il faut factoriser tous les formulaires dans le même v-dialog, et les afficher conditionnellement. VueJS nous offre la possibilité de créer des composants dynamiques, et ça pourrait être une solution, mais il faudrait alors conserver la logique de différenciation dans le composant de listing et ce serait au détriment de sa réutilisabilité, de son indépendance et de la faciliter à le tester.

Solution avec vue-router

Bien heureusement, nous avons la librairie de routing client vue-router à disposition et c’est l’outil idéal pour transférer cette responsabilité dans un fichier de configuration facilement modifiable et surtout extensible.

Plutôt qu’un composant dynamique, on va alors utiliser une router-view.

La liste va être présente sur la route mère et on peut lui ajouter autant d’enfants que l’on veut, en associant chacune d’elle avec son composant.

Au passage, il est intéressant d’activer le props: true pour passer les props en tant que paramètres de la route et découpler le composant du router.

Puisque la router-view est à l’intérieur de la modale, elle sera remplacée par le composant défini dans notre router.

Il ne nous manque plus qu’un moyen d’activer la modale, d’autant plus si on veut rendre possible l’arrivée sur la page de formulaire directement sans naviguer depuis la liste. Pour cela on va utiliser l’attribut meta, qui permet de faire passer des données relatives à la route, ici on veut que ces routes soient liées à l’apparition d’une modale donc on va ajouter un dialog = true à chacune d’elle.

Ensuite on peut utiliser la valeur stockée en meta de la route
courante en tant que v-model de notre pop-up.

Il faut seulement tenir compte que pour refermer le v-dialog, on veut juste retourner à la route mère qui n’a pas de pop-up à afficher

Composants intermédiaires

Pour complètement finir de retirer la responsabilité de la gestion des données du formulaire du composant de listing, on va passer par des composants Create / Delete / Update, ils permettent de :

  • Gérer l’affichage d’un formulaire ou d’un autre selon les paramètres (contenus dans les props)
  • Extraire la logique de la liste
  • Gérer la soumission, l’annulation ou tout autre évènement du formulaire
  • Formater la donnée avant son enregistrement

Notre composant CardUpdate.vue

Si on prend en exemple ce composant CardUpdate, on voit qu’on utilise le CardForm créé précédemment. Si on avait un type de ressource qui nécessitait un autre formulaire, on pourrait s’occuper de traiter les conditions ici.

La mécanique pour refermer le formulaire est toujours de revenir vers notre page principale qui a été définie dans le router pour ne pas avoir de fenêtre de dialogue.
Pas besoin de traitement lourd pour cet exemple mais on pourrait bien imaginer un formatage de données avant de l’envoyer à une API, ou bien la récupération de cette donnée si elle n’avait pas été chargée entièrement auparavant.

De la même manière, un composant CardCreate nous permet d’ajouter un élément à notre liste.

Conclusion

Nous avons donc vu une possibilité de création et d’édition efficace et facile à maintenir avec VueJS et vue-router, grâce à la possibilité d’intégrer des router-view à l’intérieur de composants et de les afficher en fonction de l’url des pages de notre application.
On notera également qu’il est possible de passer des variables à nos composants en tant que props, ce qui ne les contraint pas à une utilisation uniquement à travers vue-router.
On a aussi vu qu’il est tout à fait possible via ce procédé d’afficher différents composants, que ce soit un formulaire complet ou une simple pop-up de confirmation.

Cette architecture a en partie été inspirée par le client-generator d’API-platform, n’hésitez pas à aller consulter ce projet également.
https://api-platform.com/docs/client-generator/

Le code complet de cet exemple est disponible dans ce repository : https://github.com/Eddinos/modal-forms

Et il est possible de consulter un exemple à cette adresse : https://modal-forms.netlify.com/

 

Eddine D.

Ajouter un commentaire