web-dev-qa-db-fra.com

Validation côté client - le gestionnaire d'événements personnalisé n'est pas appelé lorsque l'utilisateur entre dans le champ et le laisse vide

Je travaille sur un JForm avec quelques champs avec des gestionnaires d'événements personnalisés pour faire la validation du formulaire côté client comme il est décrit dans ce document

Le document indique que "Joomla ajoute un gestionnaire de flou pour valider le champ de formulaire lorsque l'utilisateur s'éloigne du champ."

Lorsque je tape quelque chose dans le champ de texte et que j'appuie sur tab ou clique sur un autre champ, mon gestionnaire d'événements personnalisé est appelé et tout fonctionne correctement. Cependant, lorsque j'entre dans le champ puis le laisse sans taper quoi que ce soit, ou entre le champ, saisissez quelque chose, supprimez-le puis quittez le champ : le le gestionnaire d'événements n'est pas appelé du tout, je ne peux donc pas afficher d'avertissement pour l'utilisateur.

Comment puis-je m'assurer que mon gestionnaire d'événements personnalisé est appelé même dans ces cas?

Les sources: Le formulaire xml (non complet):

<form>
    <fields name="main">
        <fieldset name="basic" addfieldpath="/modules/mod_gngcontactmultiloc/models/fields">
            <field
                name="Email"
                type="text"
                label="MOD_GNGCONTACT_EMAIL"
                size="20"
                maxlenght="100"
                class="validate-myemail gngcontact"
            />

le fichier modèle (incomplet):

    <?php 
    // No direct access
    defined('_JEXEC') or die;
    JHtml::_('behavior.formvalidator');
    JHtml::_('behavior.tooltip');
    ?>
    <script>

        jQuery(document).ready(function(){
           document.formvalidator.setHandler('myemail', function(value) {
              alert("hello");
              regex=/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
              var result = regex.test(value);
              if (result) {
                document.getElementById("msg-main[Email]").style.display = 'none';
              } 
              else 
              {
                document.getElementById("msg-main[Email]").style.display = 'block';
              };
              return result;
           });
        }); 

...

<form method="post" id="contactForm" name="contactForm" class="form-validate gngcontact">
... 

L'alerte dans le code ci-dessus s'affiche si je quitte le champ après avoir tapé quelque chose, mais ne s'affiche pas dans les scénarios décrits en gras ci-dessus.

MISE À JOUR: La conclusion finale de @Zollie est juste, en utilisant l'attribut "required", la validation Joomla standard entre en jeu même dans ce cas spécial et change le champ en rouge. Malheureusement, cela n'a pas été suffisant pour moi car je voulais avoir une icône et un message de validation personnalisés affichés par un gestionnaire d'événements personnalisé et il semble que le gestionnaire d'événements personnalisé ne soit pas appelé dans ce cas particulier. J'ai donc dû implémenter ma validation côté client à partir de zéro sans utiliser le mécanisme Joomla intégré.

Merci, W.

1
wanderlusted

J'ai supprimé ma réponse précédente, car elle était vraie sur certains points mais ne répondait pas exactement à la question. Mon esprit était flou par la question. :) La question est très délicate. Pourquoi?

Parce que dans la question, le document Joomla lié indique clairement que pour que les fonctions de validation jQuery soient allumées sur votre formulaire, vous devez ajouter le formulaire de validation classe à votre forme comme:

<form class="form-validate"> ... </form>

Maintenant, je ne vois rien de mentionné à ce sujet dans la question. Dans la question, vous voyez un formulaire Champ mais vous ne voyez pas le formulaire lui-même . Vous voyez, c'est délicat parce que de cette façon "vous ne découvrirez jamais" quel est le vrai problème et si le Form a la classe importante ajoutée ou pas finalement . Nous savons maintenant seulement que l'événement Blur ne fonctionne pas sur le champ Formulaire. Et nous nous concentrons sur le terrain et sur le script. Mais pas sur le de lui-même. Ainsi, l'effet de flou commence à fonctionner sur nous. :)

Il est vrai que quelque chose peut se produire sur le terrain, une certaine validation lorsque vous donnez le champ validate-email nom de classe par exemple, mais selon le document vous devez également donner la classe form-validate au formulaire lui-même également.

Et si la classe correcte est ajoutée au formulaire , nous pourrions voir si le script est incorrect ou non, ou s'il vérifie un champ par rapport à la vacuité. Étant donné que dans le script donné dans la question, il ne semble pas que la fonction vérifie par rapport aux champs de formulaire vides de toute façon.

Donc, ce qui précède pourrait être la raison de ne pas voir l'événement de flou se produire sur le formulaire.

Et je laisse juste cette courte fonction ci-dessous si quelqu'un a besoin de vérifier un champ vide sur n'importe quel champ de formulaire. :)

Comme mile supplémentaire:) J'ai écrit la fonction flou allumé dans jQuery qui pourrait également être construit dans le script Joomla original ci-dessus, mais je le donne simplement comme autonome (j'ai testé cela aussi et cela fonctionne sur le flou sur le champ de saisie si le champ reste vide)

.myformfieldclass doit être remplacé par le nom de classe de votre champ de saisie.

<script>

    jQuery('.myformfieldclass').on("blur", function(){
        if(jQuery.trim($(this).val()) === ''){
            alert('Input field can not be left blank');
        }
    });

</script>

[~ # ~] mise à jour [~ # ~] - SUR JOOMLA HANDLER AND BLUR FUNCTION

Maintenant, nous pourrions simplement laisser ce sujet pour de bon, car je ne vois aucune raison urgente de résoudre cette question, qui pourrait être traitée simplement par quelques lignes de code en quelques minutes, mais juste pour le plaisir pendant la pause-café, J'ai vérifié le javascript de validation de formulaire de Joomla et j'ai trouvé le script valide (merci aussi à @Lodder d'avoir pointé le fichier, j'étais paresseux à le rechercher). Ceci est un script totalement différent de ce qui a été essentiellement donné dans la question , donc je ne sais toujours pas d'où vient ce script dans la question de l'affiche. Voici comment Joomla vérifie la validité d'un champ de saisie d'e-mail si la validation est définie:

// Default handlers
setHandler('email', function(value, element) {
            value = punycode.toASCII(value);
            var regex = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
            return regex.test(value);
        });
        // Attach to forms with class 'form-validate'
        var forms = jQuery('form.form-validate');
        for (var i = 0, l = forms.length; i < l; i++) {
            attachToForm(forms[i]);
}

Maintenant, dans le script ci-dessus , vous pouvez voir clairement deux choses. La fonction est attachée aux formulaires qui ont la classe form-validate. Ça va. Vous pouvez également voir que la fonction de gestionnaire de champs de messagerie par défaut ne vérifie pas si le champ est vide ou non. Je ne vois toujours pas cela dans ce qui précède. Ou quelqu'un peut-il confirmer que cette expression régulière peut filtrer un champ vide? Non, mais avant cette vérification, il y a aussi une validation html5 sur les champs et ensuite le set Handler valide le champ.

Voyons maintenant où Joomla attache les champs de saisie à blur events:

Dans cette fonction:

            // Attach validate method only to fields
            else if (tagName !== 'button' && !(tagName === 'input' && $el.attr('type') === 'button')) {
                if ($el.hasClass('required')) {
                    $el.attr('aria-required', 'true').attr('required', 'required');
                }
                if (tagName !== 'fieldset') {
                    $el.on('blur', function() {
                        return validate(this);
                    });
                    if ($el.hasClass('validate-email') && inputEmail) {
                        elements[i].setAttribute('type', 'email');
                    }
                }
                inputFields.Push($el);
}

Et si la classe de champ d'entrée est définie pour valider:

// Only validate the field if the validate class is set
handler = ($el.attr('class') && $el.attr('class').match(/validate-([a-zA-Z0-9\_\-]+)/)) ? $el.attr('class').match(/validate-([a-zA-Z0-9\_\-]+)/)[1] : "";

À partir des deux courts scripts ci-dessus, vous pouvez également voir très clairement que tous les input fields qui est défini sur required (et si validate est défini dans le nom de la classe et non dans button et fieldset), tous ces champs d'entrée sont donc envoyés pour valider sur flou ! Lié à l'événement Flou . Il n'est donc pas question si le flou s'enflamme ou non sur ces champs. Ces champs d'entrée sont liés à un événement flou, sans échappement.

Donc, je ne comprends toujours pas d'où vient le problème, ce qui est expliqué dans la question d'origine. Cependant, il peut arriver que j'oublie quelque chose dans ce fichier. Je n'ai pas eu trop de temps.

Mais si quelqu'un peut trouver quelque chose d'intéressant, veuillez être mon invité: :)

https://github.com/joomla/joomla-cms/blob/staging/media/system/js/validate-uncompressed.js

[~ # ~] enfin [~ # ~]

La seule façon dont j'aurais pu vérifier le tout est de créer un champ e-mail et de vérifier si le flou Joomla se déclenche ou non si je clique dans le champ et laissez-le vide alors, sans rien taper dans le champ. Ce que j'ai trouvé est que la validation de Joomla sur le flou ne se déclenche (si le champ est laissé vide) que lorsque le champ est défini sur required validate-email. C'est donc la seule solution à cette question. La validation de Joomla sur le flou entre en jeu sans problème si le champ est required, mais alors seulement.

Voici ma courte image enregistrée sur son fonctionnement:

enter image description here

Vous pouvez voir que sur flou, la validation entre en jeu dans un champ vide, sans exception (si le champ est obligatoire). Si le champ n'est pas défini sur obligatoire, sur le flou, rien ne se produit sur vide.

C'est le verdict final sur ce sujet. :) Le flou Joomla fonctionne.

3
Zollie

N'aimeriez-vous pas ajouter required comme classe supplémentaire sur le terrain? Sur la page https://docs.joomla.org/Special:MyLanguage/Client-side_form_validation , <field name="email" type="text" class="required validate-email" size="30" /> Suggère que vous pouvez simplement ajouter required à la fin de class="validate-myemail gngcontact".

Quant à votre javascript, je n'ai que quelques notes pour suivre mon extrait:

<script>
  jQuery(document).ready(function() {
    document.formvalidator.setHandler('myemail', function(value) {
      alert("Validating value: " + value);
      let regex=/^(?:"[^"]+"|[^<>()[\]\\.,;:\s@"]+(?:\.[^<>()[\]\\.,;:\s@"]+)*)@(?:\[\d{1,3}(?:\.\d{1,3}){3}]|(?:[a-z\d-]+\.)+[a-z]{2,})$/i;
      let result = regex.test(value);
      if (result) {
          JQuery("input[name='email']").hide();
      } else {
          JQuery("input[name='email']").show();
      }
      return result;
    });
  });
</script>
  • Vous aviez quelques groupes de capture supplémentaires qui n'étaient pas nécessaires pour maintenir la logique du modèle d'expression régulière - je les ai donc supprimés
  • J'ai converti des groupes de capture en groupes de non-capture pour indiquer qu'il n'y a aucune intention de renvoyer l'une des sous-chaînes dans la sortie. Il s'agit davantage d'une question de préférence personnelle; cela n'améliore pas l'efficacité et rend le modèle plus long en ajoutant ?: après chaque ( - vous pouvez donc ignorer cet ajustement si vous le souhaitez
  • Il n'est pas nécessaire d'échapper les accolades carrées à l'intérieur d'une classe de caractères. Les tirets n'ont pas besoin d'être échappés s'ils sont le premier ou le dernier caractère de la déclaration ou s'ils suivent une "plage de caractères"
  • \d Est identique à 0-9
  • Vous pouvez utiliser [a-z] Pour couvrir tous les caractères alphabétiques si vous ajoutez le modificateur i à la fin de votre modèle
  • Le meilleur conseil est probablement d'utiliser une classe de caractères inversée avec " Et un quantificateur gourmand pour une meilleure efficacité. Cela peut ne pas avoir beaucoup d'impact sur ce script, mais c'est une meilleure pratique que tout le monde ne connaît pas. ".+" N'est pas identique à "[^"]+". Le premier, dans certains scénarios, sera "sur-match". Ce dernier se comporte comme ".+?" Mais est plus efficace.

Voici une démonstration de modèle, si vous souhaitez voir la répartition officielle ou tester des chaînes d'entrée: https://regex101.com/r/sua8lS/1/

Je ne sais pas si j'ai bien vos sélecteurs, mais jQuery vous permet d'implémenter les actions littérales show() et hide() - ce qui est très facile pour les yeux.

1
mickmackusa