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

84

Je peux faire apparaître les popovers en utilisant le bootstrap assez facilement, et je peux également faire des validations en utilisant le plugin de validation jQuery standard ou le moteur de validation jQuery , mais je ne peux pas comprendre comment alimenter l'un dans l'autre.

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

Tout est bien 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 moteur de validation. Ils semblent tous les deux déterminés à assumer la responsabilité d'afficher des notifications avec toutes sortes d'options élaborées pour le placement, les wrappers, les styles lorsque tout ce que je cherche est le ou les types d'erreur (je n'ai même pas nécessairement besoin de texte de message) et l'élément auquel il se rapporte à. J'ai trouvé des crochets 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 jouent bien avec les formulaires créés dynamiquement.

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

Synchro
la source

Réponses:

21

Jetez un œil aux optionshighlight et showErrors jQuery Validator , celles-ci vous permettront de connecter vos propres mises en évidence d'erreur personnalisées qui déclenchent les popovers Bootstrap.

Chris Fulstow
la source
C'est génial merci. mettre en évidence et non mettre en évidence sont ce que je recherchais.
Synchro
80

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); 
    }
});

entrez la description de l'image ici

Il n'utilise pas vraiment de popovers bootstrap, mais il est vraiment joli et facile à réaliser.

MISE À 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:

entrez la description de l'image ici

Découvrez le jsFiddle .

Kenny Meyer
la source
3
J'ai voté pour parce que c'est dans le sens de ce que je recherchais. :-) Voir ma réponse pour une variante.
namin
Que faire s'il s'agit d'un formulaire à plusieurs étapes
Tachyons
4
Notez simplement qu'avec la dernière version de Bootstrap, il n'y a plus de clé .data ("popover"). Peut-être pour éviter une collision, ils ont changé la clé en "bs.popover". Il m'a fallu un certain temps pour comprendre pourquoi j'obtenais une erreur indéfinie . Alors maintenant, vous devrez utiliser _popover.data ("bs.popover"). Options.content = value.message; dans le code ci-dessus.
davidethell le
Comment puis-je afficher une fenêtre contextuelle sur un autre type d'erreur que les champs obligatoires. Je veux dire comment puis-je le personnaliser pour afficher l'erreur uniquement sur des règles spécifiques.
arjun
Il y a en fait un petit problème que vous pouvez facilement vérifier dans jsFiddle. Si le champ n'est pas obligatoire et qu'une règle est enfreinte, le popover apparaît MAIS si je vide le champ et me concentre sur un autre champ, le popover est toujours là. La première boucle de successList n'est jamais appelée, donc le popover n'est jamais dans un état "hide" après avoir été dans un état "show". Y a-t-il quelque chose que nous pouvons faire pour cela ?
G4bri3l
9

Chris Fulstow avait raison, mais cela m'a encore 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 au popover ne fonctionnaient pas, je les ai donc spécifiés en ligne dans mon entrée #password avec data-content = 'Minimum 5 characters' et data-original-title = 'Invalid Password'. 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 de comment résoudre ce problème?

Varun Singh
la source
6

Voici un suivi de l'excellente suggestion de Varun Singh qui empêche le problème de "scintillement" de la validation en essayant constamment de "montrer" même si le popup 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'
});
Jeffrey Gilbert
la source
C'était la seule réponse sur cette page qui a fonctionné pour moi. Dommage qu'il n'ait pas été voté davantage.
alastairs
1
Cela ne signifie-t-il pas que vous devez définir un explicite popoverpour chaque champ que vous souhaitez valider? Si c'est le cas, c'est fou .
g33kz0r
Pour la plupart des cas d'utilisation, je m'attendrais à ce que cela soit parfaitement acceptable. Si vous avez une solution plus optimale, n'hésitez pas à l'ajouter :)
Jeffrey Gilbert
3

Je préfère changer le CSS de bootstrap. Je viens d'ajouter les classes de jQuery validate 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;
}
Alberto Chvaicer
la source
Cette approche me convient le mieux :). C'est aussi ce que je pensais
Freshblood
3

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');
    }});
Jamie R Rytlewski
la source
3

Veuillez jeter un oeil à ce qui suit:
- https://gist.github.com/3030983
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');

        });

    }

});
Codémateur
la source
Merci beaucoup pour la tête! Voir ma version pour Bootstrap mais avec des info-bulles. À mon avis, c'est plus élégant que les popovers.
Adrian P.
3

Merci beaucoup pour la tête! Voici ma version pour Bootstrap mais avec des info-bulles. À mon avis, c'est plus élégant que les popovers. Je sais que la question portait sur les popovers, alors veuillez ne pas voter pour cette raison. Peut-être que quelqu'un l'aimera de cette façon. J'adore quand je cherche quelque chose et que j'ai trouvé de nouvelles idées sur Stackoverflow. Remarque: aucun balisage sur le formulaire 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');

            });

        }

    }); 
Adrian P.
la source
1
J'ai essayé d'utiliser votre approche, mais je commençais à avoir des erreurs. Et le problème est que si vous utilisez Jquery UI, vous obtiendrez un conflit car les deux utilisent une info-bulle. Je sais qu'il existe une solution pour cela, mais je veux juste que les autres utilisateurs le sachent.
Richard Pérez
+1 Pour jQuery UI, attention! Vous devrez configurer votre téléchargement personnalisé (jQueryUI ou Bootstrap) pour ne PAS inclure les fonctions Tooltip JS. Ce sera de toute façon un conflit pour toute info-bulle si vous ne l'avez pas fait.
Adrian P.
hé là, j'essayais d'utiliser votre code avec regex et j'ai eu une erreur sur stackoverflow.com/questions/16087351/… . Pensez-vous pouvoir aider? :)
psharma
@psharma Rien à voir avec bootstrap ou tooltip. Votre erreur est votre déclaration de règle lorsque vous avez obtenu une réponse à votre question. le message d'erreur disait: les termes ne sont pas définis!
Adrian P.
Pour une raison quelconque, c'est la seule solution qui a fonctionné pour moi. Merci!
suchanoob
2

C'est ainsi que je l'ai fait. Mais cela implique d'apporter 2 modifications au script de validation (j'ai obtenu le code pour bootstrap 1.4 ici et je l'ai ensuite modifié - http://mihirchitnis.net/2012/01/customizing-error-messages-using-jquery-validate-plugin- pour-twitter-bootstrap / )

Mon appel pour 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éez une partie d'é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, car showLabel est appelé après la mise en évidence.

Andrej Bergant
la source
2

C'est ce que j'ai mis dans ma validation pour me conformer aux directives Twitter Bootstrap. Le message de validation d'erreur est placé dans un <span class=help-inline>et nous voulons mettre en évidence le conteneur externe comme un errorou 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');
}
namin
la source
2

Voici une mise à jour de l'excellente réponse de Kenny Meyer ci-dessus . Il y a eu quelques problèmes qui l'ont empêché de fonctionner pour moi, que j'ai résolus 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");
        });
    }
tofirius
la source
Merci pour l'initiative. Le code a beaucoup changé comme je peux le voir :-)
Kenny Meyer
1

Je ne sais pas si cela est pertinent pour la discussion car l'affiche originale a demandé des crochets pour afficher / masquer les popovers bootstrap.

Je cherchais une validation simple et les popovers n'avaient pas d'importance. Un message connexe et le premier dans les résultats de recherche Google ont déjà été marqués en double de cette question. Il était donc logique de mentionner cet excellent jqValidation JS de @ ReactiveRaven, justement appelé jqBootstrapValidation, qui se marie bien avec Twitter Bootstrap. La configuration ne prend que quelques minutes. Téléchargez ici .

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

uchamp
la source
1

tl; dr évite 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 (mashup Jeffrey Gilbert et Kenny Meyer approches).

Voici mon point de vue, qui corrige le problème de scintillement mentionné par d'autres, mais contrairement à la réponse de @Jeffrey Gilbert, n'utilise pas une liste ( errorStates) mais utilise plutôt une carte d' erreur . Cartes de hachage FTW. Je pense que je me souviens avoir lu quelque part que chaque problème dans CS peut ê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 publié des idées à ce sujet.

g33kz0r
la source
0

Si vous utilisez le code Kenny Meyer ci-dessus pour les fenêtres contextuelles, méfiez-vous que les règles qui vérifient le contenu d'un champ mais qui ne sont pas obligatoires, comme une URL valide, feront que la fenêtre contextuelle ne disparaîtra pas lors de la suppression du champ. Voir ci-dessous onkeyup pour la solution. Si quelqu'un a une meilleure solution, veuillez poster.

onkeyup: function(element, event) {
            if($(element).valid())  {
                return $(element).popover("hide");
            }
        }
mousson
la source