Wie verwende ich Twitter Bootstrap-Popover für Benachrichtigungen zur jQuery-Validierung?

84

Ich kann Popovers mit Bootstrap leicht genug anzeigen lassen und ich kann auch Validierungen mit dem Standard- Plugin für die jQuery-Validierung oder der jQuery-Validierungs-Engine durchführen , aber ich kann nicht herausfinden, wie man sie ineinander überführt.

Ich denke, was ich brauche, ist ein Hook, der vom Validator aufgerufen wird, wenn er eine Benachrichtigung anzeigen möchte. Geben Sie ihm einen Abschluss, der die Nachricht und das Zielelement an ein Popover weiterleitet. Dies scheint eine Art Abhängigkeitsinjektion zu sein.

Theoretisch alles schön, aber ich kann einfach nicht herausfinden, wo sich dieser Hook befindet oder ob einer in einer der Validierungs-Engines vorhanden ist. Beide scheinen darauf bedacht zu sein, die Verantwortung für die Anzeige von Benachrichtigungen mit allen Arten von ausgefeilten Optionen für Platzierung, Wrapper und Stile zu übernehmen, wenn ich nur die Fehlertypen (ich brauche nicht unbedingt den Nachrichtentext) und das Element, auf das sie sich beziehen, suche zu. Ich habe Hooks für das gesamte Formular gefunden, nicht für die einzelnen Benachrichtigungen.

Ich bevorzuge Validierungssysteme, die Klassen zum Definieren von Regeln verwenden, da sie gut mit dynamisch erstellten Formularen spielen.

Hat jemand eine Lösung oder eine bessere Idee?

Synchro
quelle

Antworten:

21

Schauen Sie sich die Optionenhighlight und showErrors jQuery Validator an . Mit diesen Optionen können Sie Ihre eigenen benutzerdefinierten Fehlerhervorhebungen einbinden, die Bootstrap-Popover auslösen.

Chris Fulstow
quelle
Das ist großartig Danke. Highlight und Unhighlight sind das, wonach ich gesucht habe.
Synchro
80

Dies ist ein praktisches Beispiel:

$('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); 
    }
});

Geben Sie hier die Bildbeschreibung ein

Es werden keine Bootstrap-Popover verwendet, aber es sieht wirklich gut aus und ist leicht zu erreichen.

AKTUALISIEREN

Um eine Popover-Validierung zu erhalten, können Sie diesen Code verwenden:

$("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");
    });
  }
});

Sie bekommen so etwas:

Geben Sie hier die Bildbeschreibung ein

Schauen Sie sich die jsFiddle an .

Kenny Meyer
quelle
3
Upvoted, weil dies in die Richtung geht, nach der ich gesucht habe. :-) Siehe meine Antwort für eine Variante.
Namin
Was tun, wenn es sich um eine mehrstufige Form handelt
Tachyons
4
Nur eine kurze Anmerkung, dass es mit der neuesten Version von Bootstrap keinen .data-Schlüssel ("Popover") mehr gibt. Vielleicht haben sie den Schlüssel in "bs.popover" geändert, um eine Kollision zu vermeiden. Ich habe eine Weile gebraucht, um herauszufinden, warum ich einen undefinierten Fehler erhalten habe. Jetzt müssen Sie _popover.data ("bs.popover") verwenden. Options.content = value.message; im obigen Code.
Davidethell
Wie kann ich ein Popup für einen anderen Fehlertyp als die erforderlichen Felder anzeigen? Ich möchte damit sagen, wie ich es so anpassen kann, dass Fehler nur bei bestimmten Regeln angezeigt werden.
Arjun
Es gibt tatsächlich ein kleines Problem, das Sie auch in der jsFiddle leicht überprüfen können. Wenn das Feld nicht benötigt wird und eine Regel verletzt ist, wird das Popover angezeigt, ABER wenn ich das Feld entleere und mich auf ein anderes Feld konzentriere, ist das Popover immer noch vorhanden. Die erste Schleife in der successList wird niemals aufgerufen, daher befindet sich das Popover niemals in einem "Versteck" -Zustand, nachdem es in einen "Show" -Zustand versetzt wurde. Können wir etwas dagegen tun?
G4bri3l
9

Chris Fulstow hatte es richtig gemacht, aber es hat noch eine Weile gedauert, also hier ist der vollständige Code:

Dies zeigt das Popover bei einem Fehler an und verbirgt die Standardfehlerbezeichnungen:

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

Dadurch wird das Popover eingerichtet. Das einzige, was Sie dafür brauchen, ist Trigger: 'manuell'

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

Die an Popover übergebenen Titel- und Inhaltsattribute funktionierten nicht, daher habe ich sie in meiner # Passwort-Eingabe mit Dateninhalt = 'Mindestens 5 Zeichen' und Daten-Originaltitel = 'Ungültiges Passwort' inline angegeben. Sie benötigen außerdem rel = 'popover' in Ihrem Formular.

Dies funktioniert, aber der Popover flackert, wenn die Auswahl aufgehoben wird. Irgendeine Idee, wie man das behebt?

Varun Singh
quelle
6

Hier ist eine Fortsetzung des hervorragenden Vorschlags von Varun Singh, der verhindert, dass das "Flimmern" der Validierung ständig versucht, "zu zeigen", obwohl das Popup bereits vorhanden ist. Ich habe einfach ein Fehlerstatus-Array hinzugefügt, um zu erfassen, welche Elemente Fehler anzeigen und welche nicht. Klappt wunderbar!

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
quelle
Dies war die einzige Antwort auf dieser Seite, die für mich funktioniert hat. Schade, dass es nicht mehr gewählt wurde.
Alastairs
1
Bedeutet dies nicht, dass Sie popoverfür jedes einzelne Feld, das Sie validieren möchten, eine explizite Definition definieren müssen ? Wenn ja, ist das verrückt .
g33kz0r
Für die meisten Anwendungsfälle würde ich erwarten, dass dies vollkommen akzeptabel ist. Wenn Sie eine optimalere Lösung haben, können Sie diese gerne hinzufügen :)
Jeffrey Gilbert
3

Ich ziehe es vor, das CSS von Bootstrap zu ändern. Fügen Sie einfach die Klassen von jQuery validate an der richtigen Stelle hinzu. Feldvalidierungsfehler und Eingabevalidierungsfehler

    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
quelle
Dieser Ansatz sieht für mich am besten aus :). Dies ist auch, was ich dachte
Freshblood
3

So habe ich es mit Bootstrap 2.x und jQuery Validate 1.9 gemacht

$('#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
quelle
3

Bitte schauen Sie sich Folgendes an:
- https://gist.github.com/3030983
Ich denke, es ist das einfachste von allen.

BEARBEITEN

Code vom Link:

$('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');

        });

    }

});
Codemator
quelle
Vielen Dank für das Heads Up! Siehe meine Version für Bootstrap, aber mit Tooltips. Meiner Meinung nach ist es eleganter als Popovers.
Adrian P.
3

Vielen Dank für das Heads Up! Hier ist meine Version für Bootstrap, aber mit Tooltips. Meiner Meinung nach ist es eleganter als Popovers. Ich weiß, dass die Frage für Popover war, also stimmen Sie aus diesem Grund bitte nicht ab. Vielleicht wird es jemandem so gefallen. Ich liebe es, wenn ich nach etwas suche und neue Ideen für Stackoverflow gefunden habe. Hinweis: Es ist kein Markup auf dem Formular erforderlich.

    $('#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.
quelle
1
Ich habe versucht, Ihren Ansatz zu verwenden, aber ich fing an, Fehler zu bekommen. Das Problem ist, wenn Sie die Jquery-Benutzeroberfläche verwenden, kommt es zu Konflikten, da beide Tooltips verwenden. Ich weiß, dass es dafür eine Lösung gibt, möchte aber nur andere Benutzer darüber informieren.
Richard Pérez
+1 Für jQuery UI Heads Up! Sie müssen Ihren benutzerdefinierten Download (jQueryUI oder Bootstrap) so konfigurieren, dass KEINE Tooltip JS-Funktionen enthalten sind. Es ist ohnehin ein Konflikt für jeden Tooltip, wenn Sie dies nicht getan haben.
Adrian P.
Hey, ich habe versucht, Ihren Code mit Regex zu verwenden und habe zufällig einen Fehler unter stackoverflow.com/questions/16087351/… . Glaubst du, du kannst helfen? :)
Psharma
@psharma Nichts mit Bootstrap oder Tooltip zu tun. Ihr Fehler ist Ihre Regelerklärung, da Sie eine Antwort auf Ihre Frage erhalten haben. Die Fehlermeldung lautete: Begriffe sind undefiniert!
Adrian P.
Aus irgendeinem Grund ist dies die einzige Lösung, die für mich funktioniert hat. Vielen Dank!
Suchanoob
2

So habe ich es geschafft. Es sind jedoch zwei Änderungen am Validierungsskript erforderlich (ich habe hier den Code für Bootstrap 1.4 erhalten und ihn dann geändert - http://mihirchitnis.net/2012/01/customizing-error-messages-using-jquery-validate-plugin- for-twitter-bootstrap / )

Mein Aufruf zur Bestätigung:

    $("#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);
    }
  }
});

Dann müssen Sie zwei Dinge in jquery.validate.js ändern.
1. Wenden Sie diesen Fix an - https://github.com/bsrykt/jquery-validation/commit/6c3f53ee00d8862bd4ee89bb627de5a53a7ed20a
2. Erstellen Sie nach Zeile 647 (in der Funktion showLabel den Etikettenteil ) nach Zeile Zeile .addClass(this.settings.errorClass)hinzufügen: .addClass("help-inline")
Jemand kann vielleicht einen Weg finden, den zweiten Fix in der Validierungsfunktion anzuwenden, aber ich habe keinen Weg gefunden, da showLabel nach Hervorhebung aufgerufen wird.

Andrej Bergant
quelle
2

Dies ist, was ich in meine Validierung eingefügt habe, um den Twitter Bootstrap-Richtlinien zu entsprechen. Die Fehlerüberprüfungsnachricht wird in a <span class=help-inline>eingefügt und wir möchten den äußeren Container als erroroder hervorheben 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
quelle
2

Hier ist ein Update zu Kenny Meyers ausgezeichneter Antwort oben . Es gab einige Probleme, die verhindert haben, dass es für mich funktioniert, die ich in diesem Ausschnitt angesprochen habe:

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
quelle
Vielen Dank für die Initiative. Der Code hat sich sehr verändert, wie ich sehen kann :-)
Kenny Meyer
1

Ich bin mir nicht sicher, ob dies für die Diskussion relevant ist, da im Originalposter nach Hooks zum Ein- / Ausblenden von Bootstrap-Popovers gefragt wurde.

Ich suchte nach einer einfachen Validierung und Popovers spielten keine Rolle. Ein verwandter Beitrag und der erste in den Google-Suchergebnissen wurden bereits als Duplikat dieser Frage markiert. Daher war es sinnvoll, das ausgezeichnete jqValidation JS von @ ReactiveRaven zu erwähnen, das treffend als jqBootstrapValidation bezeichnet wird und gut mit Twitter Bootstrap harmoniert. Die Einrichtung dauert nur wenige Minuten. Laden Sie hier .

Hoffe das schafft Mehrwert.

uchamp
quelle
1

tl; dr vermeiden , um explizite popovers aufzuzählen durch eine Hash - Tabelle mit den IDs der Elemente zu speichern, und die Schaffung von popovers on-the-fly (Mashup Jeffrey Gilbert und Kenny Meyers Ansätze).

Hier ist mein nehmen, die das Flackern Problem von anderen erwähnt behebt, aber im Gegensatz zu @Jeffrey Gilberts Antwort, verwendet keine Liste ( errorStates) , sondern verwendet eine Fehler Karte . Hash-Karten FTW. Ich denke, ich erinnere mich, dass ich irgendwo gelesen habe, dass jedes Problem in CS mit einer Hash-Map gelöst werden kann :)

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

Vielen Dank an alle anderen, die Ideen dazu gepostet haben.

g33kz0r
quelle
0

Wenn Sie den obigen Kenny Meyer-Code für Popups verwenden, beachten Sie, dass Regeln, die den Inhalt eines Felds überprüfen, aber nicht erforderlich sind, z. B. eine gültige URL, dazu führen, dass das Popup beim Löschen des Felds nicht verschwindet. Siehe unten onkeyup für die Lösung. Wenn jemand eine bessere Lösung hat, bitte posten.

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