Champs de formulaire avec v-model dans les slots nommés5 min read

Ideas waiting to be had

Dans cet article, je vous donne mon retour d’expérience sur les solutions que j’ai trouvé à un problème que j’ai rencontré : utiliser des champs de formulaires avec l’attribut v-model dans des slots nommés (scoped slots).

Les slots nommés et v-model

VueJS fournit une fonctionnalité plutôt utile lorsqu’il s’agit de garder son code DRY (Don’t repeat yourself) : les slots. Si vous ne savez pas ce qu’est un slot, voici un exemple : la boîte de dialogue.

Elle se comporte toujours de la même façon. Quand on l’ouvre, cela crée une fenêtre par-dessus la vue courante. Cette fenêtre a habituellement un titre, un contenu, et quelques boutons. Et ce contenu peut être n’importe quoi ! Du simple texte, un formulaire, une image, une combinaison de tout ça… Dans ce cas, est-ce qu’on développerait pas une nouvelle boîte de dialogue pour chaque type de contenu ? Sûrement pas ! On utiliserait des slots. On créerait un composant qui s’occuperait d’afficher une fenêtre par-dessus la vue courante, et on y placerait un slot pour le contenu.

Mais vous savez probablement déjà tout ça. Le sujet de cet article est un cas particulier que j’ai eu à appréhender : les champs de formulaires dans des slots. Les champs de formulaires sont un cas intéressant parce que VueJS fournit un attribut particulier pour eux : v-model. Un champ utilisant v-model va garder synchronisée la valeur affichée dans ce dernier, et la variable JavaScript à laquelle il est lié.

v-model ne fonctionne pas comme ça

Pour cet article, je vais prendre l’exemple d’un formulaire dynamique. Disons qu’on voudrait construire un formulaire avec des champs <input> et <textarea> (qui permettent l’utilisation de v-model). Et qu’avec chacun de ces champs on veuille afficher un avertissement s’il est vide. Une option serait de crée un nouveau jeu de composants basés sur <input> pour l’un et <textarea> pour l’autre, en ajoutant cette nouvelle fonctionnalité au passage. Nous utiliserions ces nouveaux composant à la place des premiers dans le formulaire. Une meilleure option serait de créer un seul nouveau composant, qu’on appellerait FormElement, et qui implémenterait cette nouvelle fonctionnalité, et qui aurait un slot pour le champ de formulaire.

Créons donc ce composant :

Dans le slot, on passe la variable qui contient la valeur du champ. De cette manière elle peut être consommée par le champ <input> ou <textarea>.

Dans notre formulaire, on utilise le mot-clé v-model sur les champs <input> et <textarea>, parce qu’on fait toujours comme ça :

Malheureusement ça ne fonctionne pas. En fait ce code ne compile même pas. Le message d’erreur suivant devrait s’afficher :

‘v-model’ directives cannot update the iteration variable ‘value’ itself

Et on aurait dû la voir venir cette erreur. Les valeurs passées aux slots sont en lecture seule. Donc v-model ne peut pas en changer la valeur.

Il y a bien-sûr une multitude de solutions à ce problème. Je vais vous donner mes deux préférées.

Première solution : exploser v-model

v-model est l’une des fonctionnalités emblématiques de VueJS. Il fait partie des premières choses qui nous sont enseignées lorsqu’on découvre ce framework. Et c’est probablement pour ça que nous oublions (ou ne savons même pas) comment il fonctionne. Comme montré dans la documentation officielle, v-model remplace l’utilisation de :value et @input. C’est comme ça que la magie opère. Quand la variable liée change (:value), la valeur du champ est mise à jour, et quand l’utilisateur tape quelque-chose dans le champs (@input), la variable liée est mise à jour.

Donc ce qu’on pourrait faire, c’est utiliser cette forme explosée de v-model, et passer une fonction au slot nommé pour mettre la variable à jour.

Voilà ce que ça donne :

Ce que j’aime dans cette solution c’est qu’elle est facile à comprendre au premier coup d’œil. Les choses sont claires.

Seconde solution : Passer le parent dans le slot

Une autre option, que j’aime car elle a l’air futée, est de passer non pas la variable contenant la valeur au slot, mais un objet contenant cette variable comme propriété. Dans notre exemple on passerait la propriété field. Et dans le slot, on attribuerait v-model à field.value.

Rappelons-nous que le JavaScript utilise toujours les références des variables. Donc quand on déclare une variable en lecture seule (plutôt const du coup), on n’est pas autorisé à changer sa valeur. Mais on sera autorisé à changer la valeur de ses propriétés.

Cette solution est plus compacte, et on a pas besoin de déclarer une nouvelle méthode pour gérer l’évènement émis lorsque l’utilisateur tape du texte dans le champ. Moins on écrit de code, moins on risque de faire des erreurs.


Merci d’avoir lu cet article. J’espère qu’il vous a plu.

N’hésitez pas à le commenter et à partager votre méthode pour gérer les champs de formulaire dans des slots.

Bonne journée !

Related Posts

Leave a Reply