web-dev-qa-db-fra.com

Comment utiliser Twitter Bootstrap popovers pour les notifications de validation jQuery?

Je peux faire apparaître assez facilement des popovers à l'aide de bootstrap , et je peux également effectuer des validations à l'aide du standard plug-in de validation jQuery ou du moteur de validation jQuery , mais Je n'arrive pas à comprendre comment introduire l'un dans l'autre.

Je pense que ce dont j'ai besoin, c'est d'un hook appelé par le validateur quand il veut afficher une notification, lui donner une fermeture qui passe le message et l'élément cible à un popover. Cela ressemble à une sorte d'injection de dépendance.

Tout est sympa en théorie, mais je ne peux tout simplement pas savoir où se trouve ce crochet, ni même s'il en existe un dans l'un ou l'autre des moteurs de validation. Ils semblent tous deux résolus à prendre la responsabilité d'afficher des notifications avec toutes sortes d'options élaborées pour le placement, les wrappers et les styles, alors que tout ce que je recherche, c'est le type d'erreur (je n'ai même pas nécessairement besoin du texte du message) et de l'élément concerné. à. J'ai trouvé des points d'ancrage pour l'ensemble du formulaire, pas pour les notifications individuelles.

Je préfère de loin les systèmes de validation qui utilisent des classes pour définir des règles, car ils fonctionnent bien avec des formulaires créés de manière dynamique.

Quelqu'un a une solution ou une meilleure idée?

84
Synchro

Jetez un coup d’œil aux highlight et showErrorsoptions du validateur jQuery , ils vous permettront d’attacher vos propres surlignages d’erreur personnalisés qui déclenchent Bootstrap popovers .

21
Chris Fulstow

Voici un exemple pratique:

$('form').validate({
    errorClass:'error',
    validClass:'success',
    errorElement:'span',
    highlight: function (element, errorClass, validClass) { 
        $(element).parents("div[class='clearfix']").addClass(errorClass).removeClass(validClass); 
    }, 
    unhighlight: function (element, errorClass, validClass) { 
        $(element).parents(".error").removeClass(errorClass).addClass(validClass); 
    }
});

enter image description here

Il n’utilise pas vraiment bootstrap popovers, mais il a vraiment l’air agréable et est facile à réaliser.

[~ # ~] met à jour [~ # ~]

Donc, pour avoir une validation popover, vous pouvez utiliser ce code:

$("form").validate({
  rules : {
    test : {
      minlength: 3 ,
      required: true
    }
  },
  showErrors: function(errorMap, errorList) {
    $.each(this.successList, function(index, value) {
      return $(value).popover("hide");
    });
    return $.each(errorList, function(index, value) {
      var _popover;
      _popover = $(value.element).popover({
        trigger: "manual",
        placement: "top",
        content: value.message,
        template: "<div class=\"popover\"><div class=\"arrow\"></div><div class=\"popover-inner\"><div class=\"popover-content\"><p></p></div></div></div>"
      });
      // Bootstrap 3.x :      
      //_popover.data("bs.popover").options.content = value.message;
      // Bootstrap 2.x :
      _popover.data("popover").options.content = value.message;
      return $(value.element).popover("show");
    });
  }
});

Vous obtenez quelque chose comme ça:

enter image description here

Découvrez le jsFiddle .

80
Kenny Meyer

Chris Fulstow avait raison, mais cela m'a pris un certain temps, alors voici le code complet:

Cela affiche le popover en cas d’erreur et masque les étiquettes d’erreur par défaut:

$('#login').validate({
  highlight: function(element, errClass) {
    $(element).popover('show');
  },
  unhighlight: function(element, errClass) {
    $(element).popover('hide');
  },
  errorPlacement: function(err, element) {
    err.hide();
  }
}).form();

Cela met en place le popover. La seule chose dont vous avez besoin est le déclencheur: 'manuel'

$('#password').popover({
  placement: 'below',
  offset: 20,
  trigger: 'manual'
});

Les attributs de titre et de contenu transmis à popover ne fonctionnaient pas, je les ai donc spécifiés en ligne dans mon entrée # mot de passe avec data-content = '5 caractères au minimum' et data-original-title = 'Mot de passe invalide'. Vous avez également besoin de rel = 'popover' dans votre formulaire.

Cela fonctionne, mais le popover scintille lors de la désélection. Une idée comment résoudre ce problème?

9
Varun Singh

Voici une suite à l'excellente suggestion de Varun Singh qui empêche le problème de la "scintillement" de la validation d'essayer de "montrer" en permanence, même si le menu contextuel est déjà présent. J'ai simplement ajouté un tableau d'états d'erreur pour capturer quels éléments affichent des erreurs et lesquels ne le sont pas. Fonctionne comme un charme!

var errorStates = [];

$('#LoginForm').validate({
    errorClass:'error',
    validClass:'success',
    errorElement:'span',
    highlight: function (element, errorClass) {
        if($.inArray(element, errorStates) == -1){
            errorStates[errorStates.length] = element;
            $(element).popover('show');
        }
    }, 
    unhighlight: function (element, errorClass, validClass) {
        if($.inArray(element, errorStates) != -1){
            this.errorStates = $.grep(errorStates, function(value) {
              return value != errorStates;
            });
            $(element).popover('hide');
        }
    },
    errorPlacement: function(err, element) {
        err.hide();
    }
});

$('#Login_unique_identifier').popover({
    placement: 'right',
    offset: 20,
    trigger: 'manual'
});

$('#Login_password').popover({
    placement: 'right',
    offset: 20,
    trigger: 'manual'
});
6
Jeffrey Gilbert

Cette extension jQuery pour le plug-in de validation jQuery (testé avec la version 1.9.0) fera l'affaire.

https://github.com/tonycoco/Rails_template/blob/master/files/assets/javascripts/jquery.validate.bootstrap.js

Cela ajoute également dans certaines messages d'erreur Rails-esk.

5
tonycoco

Je préfère changer le CSS de bootstrap. Vient d’ajouter les classes de jQuery valider au bon endroit. erreur de validation de champ et erreur de validation d'entrée

    form .clearfix.error > label, form .clearfix.error .help-block, form .clearfix.error .help-inline, .field-validation-error {
  color: #b94a48;
}
form .clearfix.error input, form .clearfix.error textarea, .input-validation-error {
  color: #b94a48;
  border-color: #ee5f5b;
}
form .clearfix.error input:focus, form .clearfix.error textarea:focus, .input-validation-error:focus {
  border-color: #e9322d;
  -webkit-box-shadow: 0 0 6px #f8b9b7;
  -moz-box-shadow: 0 0 6px #f8b9b7;
  box-shadow: 0 0 6px #f8b9b7;
}
3
Alberto Chvaicer

Voici comment je l’ai fait avec Bootstrap 2.x et jQuery Validate 1.9

$('#form-register').validate({ errorElement: 'span', errorClass:'help-inline', highlight:    function (element, errorClass) {
        $(element).parent().parent().addClass('error');
    }, unhighlight: function (element, errorClass) {
        $(element).parent().parent().removeClass('error');
    }});
3

Merci beaucoup pour le heads up! Voici ma version pour Bootstrap mais avec les info-bulles. À mon avis, il est plus élégant que les popovers. Je sais que la question visait les popovers, donc s'il vous plaît, ne votez pas pour cette raison. Peut-être que quelqu'un l'aimera bien. de cette façon. J'aime quand je cherche quelque chose et que je trouve de nouvelles idées sur Stackoverflow. Remarque: aucune annotation sur la forme n’est nécessaire.

    $('#LoginForm').validate({
        rules: {
            password: {
                required: true,
                minlength: 6
            },

            email_address: {
                required: true,
                email: true
            }
        },
        messages: {
            password: {
                required: "Password is required",
                minlength: "Minimum length is 6 characters"
            },
            email_address: {
                required: "Email address is required",
                email: "Email address is not valid"
            }
        },  
        submitHandler: function(form) {
            form.submit();
        },

        showErrors: function (errorMap, errorList) {

            $.each(this.successList, function (index, value) {
                $('#'+value.id+'').tooltip('destroy');
            });


            $.each(errorList, function (index, value) {

                $('#'+value.element.id+'').attr('title',value.message).tooltip({
                    placement: 'bottom',
                    trigger: 'manual',
                    delay: { show: 500, hide: 5000 }
                }).tooltip('show');

            });

        }

    }); 
3
Adrian P.

S'il vous plaît jeter un oeil à ce qui suit:
- https://Gist.github.com/303098
Je pense que c'est le plus simple de tous.

[~ # ~] éditer [~ # ~]

Code du lien:

$('form').validate({
    rules: {
        numero: {
            required: true
        },
        descricao: {
            minlength: 3,
            email: true,
            required: true
        }
    },

    showErrors: function (errorMap, errorList) {

        $.each(this.successList, function (index, value) {
            $(value).popover('hide');
        });


        $.each(errorList, function (index, value) {

            console.log(value.message);

            var _popover = $(value.element).popover({
                trigger: 'manual',
                placement: 'top',
                content: value.message,
                template: '<div class="popover"><div class="arrow"></div><div class="popover-inner"><div class="popover-content"><p></p></div></div></div>'
            });

            _popover.data('popover').options.content = value.message;

            $(value.element).popover('show');

        });

    }

});
3
Codemator

Voici une mise à jour de excellente réponse de Kenny Meyer ci-dessus . Quelques problèmes l'empêchant de fonctionner pour moi, que j'ai abordés dans cet extrait:

showErrors: function (errorMap, errorList) {
        $.each(this.successList, function (index, element) {
            return $(element).popover("destroy");
        });

        $.each(errorList, function (index, error) {
            var ele = $(error.element); //Instead of referencing the popover directly, I use the element that is the target for the popover

            ele.popover({
                    trigger: "manual",
                    placement: "top",
                    content: function(){ //use a function to assign the error message to content
                        return error.message
                    },
                    template: '<div class="popover"><div class="arrow"></div><div class="popover-inner"><div class="popover-content"><p></p></div></div></div>'
            });

            //bs.popover must be used, not just popover
            ele.data("bs.popover").options.content = error.message;

            return $(error.element).popover("show");
        });
    }
2
tofirius

C’est ce que j’ai mis dans ma validation pour me conformer aux directives de Twitter Bootstrap. Le message de validation d’erreur est placé dans un <span class=help-inline> et nous voulons mettre en surbrillance le conteneur externe en tant que error ou success:

errorClass:'help-inline',
errorElement:'span',
highlight: function (element, errorClass, validClass) {
$(element).parents("div.clearfix").addClass('error').removeClass('success');
},
unhighlight: function (element, errorClass, validClass) {
$(element).parents(".error").removeClass('error').addClass('success');
}
2
namin

C'est comme ça que j'ai réussi. Mais cela implique d’apporter 2 modifications au script de validation (j’ai obtenu le code pour bootstrap 1.4 ici, puis je l’ai modifié - http://mihirchitnis.net/2012/01/customizing -error-messages-using-jquery-validate-plugin-for-Twitter-bootstrap / )

Mon appel à valider:

    $("#loginForm").validate({
  errorClass: "control-group error",
  validClass: "control-group success",
  errorElement: "span", // class='help-inline'
  highlight: function(element, errorClass, validClass) {
    if (element.type === 'radio') {
        this.findByName(element.name).parent("div").parent("div").removeClass(validClass).addClass(errorClass);
    } else {
        $(element).parent("div").parent("div").removeClass(validClass).addClass(errorClass);
    }
  },
  unhighlight: function(element, errorClass, validClass) {
    if (element.type === 'radio') {
        this.findByName(element.name).parent("div").parent("div").removeClass(errorClass).addClass(validClass);
    } else {
        $(element).parent("div").parent("div").removeClass(errorClass).addClass(validClass);
    }
  }
});

Ensuite, vous devez changer 2 choses dans jquery.validate.js
1. appliquer ce correctif - https://github.com/bsrykt/jquery-validation/commit/6c3f53ee00d8862bd4ee89bb627de5a53a7ed20a
2. Après la ligne 647 (dans la fonction showLabel, créer une partie étiquette) après la ligne .addClass(this.settings.errorClass) ajouter une ligne: .addClass("help-inline")
Quelqu'un peut peut-être trouver un moyen d'appliquer le deuxième correctif dans la fonction de validation, mais je n'ai pas trouvé de moyen, puisque showLabel est appelée après la surbrillance.

2
Andrej Bergant

Commander ceci: https://github.com/mingliangfeng/jquery.validate.bootstrap.popover

Il montre comment utiliser Bootstrap popover css, au lieu de JS. La méthode contextuelle de JS provoquera un problème de clignotement.

1
Andrew Feng

tl; dr évitez d'avoir à énumérer les popovers explicites en utilisant une carte de hachage pour stocker les identifiants des éléments et en créant des popovers à la volée (approches de mashup Jeffrey Gilbert et Kenny Meyer).

Voici ma position, qui résout le problème de scintillement évoqué par d'autres, mais contrairement à la réponse de @Jeffrey Gilbert, n'utilise pas de liste (errorStates) mais utilise plutôt une erreur map . Les cartes de hachage FTW. Je pense me rappeler avoir lu quelque part que chaque problème de CS pouvait être résolu avec une carte de hachage :)

var err_map = new Object();     // <--- n.b.
$("form#set_draws").validate({
  rules: {
    myinput: { required: true, number: true },
  },
  showErrors: function(errorMap, errorList) {
    $.each(this.successList, function(index, value) {
      if (value.id in err_map)
      {
        var k = err_map[value.id];
        delete err_map[value.id]; // so validation can transition between valid/invalid states
        k.popover("hide");
      }
    });
    return $.each(errorList, function(index, value) {
      var element = $(value.element);
      if( ! (value.element.id in err_map) ) {
        var _popover = element.popover({
          trigger: "manual",
                 placement: "top",
                 content: value.message,
                 template: "<div class=\"popover\"><div class=\"arrow\"></div><div class=\"popover-inner\"><div class=\"popover-content\"><p></p></div></div></div>"
        });
        _popover.data("popover").options.content = value.message;
          err_map[value.element.id] = _popover;
        return err_map[value.element.id].popover("show");
      }
    });
  }
});

Merci à tous ceux qui ont posté des idées à ce sujet.

1
g33kz0r

Je ne sais pas si cela est pertinent pour la discussion parce que l’affiche originale a demandé que des points d’accroches soient affichés/masqués bootstrap popovers.

Je cherchais une validation simple et les popovers importaient peu. A lié et le premier dans les résultats de recherche Google a déjà été marqué comme un doublon de cette question. Il était donc logique de mentionner cet excellent @ jqValidation JS de @ ReactiveRaven, appelé à juste titre jqBootstrapValidation, qui se marie bien avec Twitter Bootstrap. L'installation ne prend que quelques minutes. Télécharger ici .

J'espère que cela ajoute de la valeur.

1
uchamp

Si vous utilisez le code Kenny Meyer ci-dessus pour les fenêtres contextuelles, sachez que les règles qui vérifient le contenu d'un champ mais ne sont pas obligatoires, comme une URL valide, feront en sorte que la fenêtre contextuelle ne disparaisse pas lorsque vous effacez le champ. Voir ci-dessous onkeyup pour la solution. Si quelqu'un a une meilleure solution, merci de poster.

onkeyup: function(element, event) {
            if($(element).valid())  {
                return $(element).popover("hide");
            }
        }
0
monsoon