Utiliser JQuery Validate avec les Dropdowns Semantic UI
J'apprécie beaucoup le style visuel apporté par Semantic-UI. Malheureusement, son module Dropdown se comporte mal avec Jquery Validate que l'on utilise beaucoup en ASP.Net Core pour proposer une validation côté navigateur en javascript des formulaires. En combinant les deux, il n'y a malheureusement aucun affichage de message d'erreur et aucun "entouré rouge" du champ. Dans cet article nous essayerons de contribuer à la maigre documentation existante en proposant une solution technique à ce soucis.
Mise en place de la liste déroulante
Pour activer la création de la liste déroulante Semantic UI, il faut partir d'un élément select HTML "classique" que nous générons ici en Razor.
<select id="DropDown" asp-for="ViewModel.BirdName" asp-items="Model.AvailableBirdNames"></select>
Côté C# j'expose une liste de valeurs possibles dans la propriété AvailableBirdNames. Aussi j'ai apposé un attribut Required sur la propriété BirdName pour demander à Razor de configurer jQueryValidate afin qu'il s'assure de la présence de ce champ à la soumission du formulaire.
Pour appliquer le style Semantic, il ne reste ensuite qu'à l'activer sur le select via du jQuery :
// apply semantic theme $('#DropDown').dropdown();
Sous le capot, Semantic UI va masquer notre select initial et créer sa propre structure HTML. Cela se voit facilement avec un inspecteur d'HTML :
Origine et correction du problème
jQuery Validate est censé bloquer la soumission d'un formulaire si une erreur est présente mais cela ne fonctionne plus en l'état à partir du moment où l'on applique le style Semantic. L'origine du problème est assez simple : le champ select est masqué (display : hidden) par Semantic et JQueryValidate ignore les champs invisibles.
La solution consiste, tout simplement, à demander à jQuery Validate de ne pas ignorer les champs masqués. Pour cela, on parcourt les formulaires de la page et on enlève la règle ignorant les champs masqués :
$("form").each(function () { var form = $(this).data("validator"); if (form) { // no field is ignored. Justice for all form.settings.ignore = ""; } });
Seulement voilà, on se trouve confronté à un nouveau problème : les méthodes permettant de passer d'un état valide à invalide et inversement de JQuery validate utilisent le mot-clef Javascript "this" pour faire référence au formulaire dans un traitement (c'est vraiment... pas recommandé) et crashe dans ce scénario d'utilisation avec Semantic UI.
Nous allons donc devoir (tricher) et surcharger les méthodes highlight et unhighlight en s'assurant de leur passer un bon contexte d'exécution. À la suite du traitement précédent, pour chaque formulaire, il faut ajouter ce code :
// keep the context of the form with bind // because jquery validate uses "this" (boooooooohhhhhh) var hl = form.settings.highlight.bind(form); form.settings.highlight = (function (el, errClass, validClass){ hl(el, errClass, validClass); if (el.nodeName.toLowerCase() === "select") { hl(el.parentNode, errClass, validClass); } }).bind(form); // keep the context of the form with bind // because jquery validate uses "this" (boooooooohhhhhh) var uhl = form.settings.unhighlight.bind(form); form.settings.unhighlight = (function (el, errClass, validClass) { uhl(el, errClass, validClass); if (el.nodeName.toLowerCase() === "select") { uhl(el.parentNode, errClass, validClass); } }).bind(form);
Une fois tout cela fait, on a (enfin) une validation qui fonctionne. Heureusement, cette méthode est générique et peut s'appliquer facilement de manière globale :
Happy coding !
Commentaires