jquery.validate.unobtrusive funktioniert nicht mit dynamisch injizierten Elementen

99

Ich arbeite mit ASP.Net MVC3, der einfachere Weg, die Client-Validierung zu verwenden, wäre die Aktivierung der jquery.validate.unobtrusive. Alles funktioniert gut, für Dinge, die direkt vom Server stammen.

Aber wenn ich versuche, einige neue 'Eingaben' mit Javascript zu versehen, wusste ich, dass ich aufrufen muss $.validator.unobtrusive.parse(), um die Validierungen erneut zu binden. Trotzdem funktionieren all diese dynamisch injizierten Felder nicht.

Schlimmer noch, ich versuche manuell mit zu binden jquery.validateund es funktioniert auch nicht. Irgendwelche Gedanken?

xandy
quelle
1
Wenn Sie von Google hierher gekommen sind, suchen Sie wahrscheinlich nach der Antwort von @Sundara Prabu, da die anderen, die massiv positiv bewertet werden, alt sind.
Der Muffin-Mann

Antworten:

65

Ich habe eine Erweiterung für die Bibliothek jquery.validate.unobtrusive erstellt, die dieses Problem für meine Situation gelöst hat - es könnte von Interesse sein.

http://xhalent.wordpress.com/2011/01/24/applying-unobtrusive-validation-to-dynamic-content/

Xhalent
quelle
Ich denke, ich sollte Ihre Antwort als die richtige wählen. Übrigens, funktioniert Ihre Bibliothek mit dem neuesten MVC RC? oder haben sie das einfach behoben?
Xandy
1
Wenn Sie den oben verlinkten Code verwenden, stellen Sie sicher, dass Sie ihn aktualisieren, um den Code in die Kommentare aufzunehmen, da er sonst beschädigt werden kann. Ändern Sie insbesondere die beiden Auswahlzeilen, um die ID in doppelte Anführungszeichen zu setzen.
Ryan O'Neill
1
Konnte dies nach einigem Debuggen endlich für mein Szenario zum Laufen bringen. Es scheint, dass nicht eine Eingabeauswahl übergeben werden sollte, sondern das übergeordnete Element oder das Formular der Eingabe aufgrund des Aufrufs von $.validator.unobtrusive.parse(). Außerdem scheint es nur neue Regeln hinzuzufügen, aber keine Aktualisierungen bestehender Regeln aufzunehmen?
Lambinator
5
Diese Antwort sollte mindestens die Bärenknochen des Blogposts enthalten. Nur-Link-Antworten sind für SO
Liam
8
Obwohl diese Antwort mindestens 3 Jahre alt ist, wäre es äußerst hilfreich, wenn Sie die wesentlichen Teile der Antwort hier auf dieser Website veröffentlichen könnten oder Ihr Beitrag möglicherweise gelöscht wird . In den häufig gestellten Fragen werden Antworten erwähnt, die kaum mehr als ein Link sind '. Sie können den Link weiterhin einfügen, wenn Sie dies wünschen, jedoch nur als 'Referenz'. Die Antwort sollte für sich allein stehen, ohne den Link zu benötigen.
Taryn
159

Ich habe Xhalents Ansatz ausprobiert, aber leider hat es bei mir nicht funktioniert. Robins Ansatz hat funktioniert und nicht funktioniert. Es funktionierte hervorragend für dynamisch hinzugefügte Elemente. Wenn Sie jedoch versuchen, mit JQuery alle Validierungsattribute und -bereiche aus dem DOM zu entfernen, versucht die Validierungsbibliothek weiterhin, sie zu validieren.

Wenn Sie jedoch zusätzlich zu "validationData" die "unauffälligen Validierungs" -Daten des Formulars entfernen, funktioniert dies wie ein Zauber zum dynamischen Hinzufügen und Entfernen von Elementen, die validiert oder nicht validiert werden sollen.

$("form").removeData("validator");
$("form").removeData("unobtrusiveValidation");
$.validator.unobtrusive.parse("form");
Viggity
quelle
2
Xhalent's hat auch bei mir zuerst nicht funktioniert, dann ist mir aufgefallen, dass beim Parsen ein Container für die neuen Elemente übergeben werden sollte, NICHT für die Elemente selbst - eine schnelle Lösung wäre, das gesamte Formular anstelle der Elemente zu übergeben - und dann Lief wie am Schnürchen.
Per Hornshøj-Schierbeck
1
Irgendeine Idee, warum es heißt, validatorist nicht definiert? Ich habe sowohl Validierung als auch Validierung. Unauffällig referenziert. Die Validierung funktioniert, bis ich diesen Code
aufrufe
4
Vielen Dank. Es funktioniert für Inhalte, die der Seite in ASP.MVC-Teilansichten hinzugefügt wurden, die über einen AJAX-Aufruf hinzugefügt wurden.
Maksym Kozlenko
Danke das hat geholfen. Ich habe jedoch ein Problem, bei dem ich Akkordeons auf der Seite verwende. Wenn das Akkordeon zusammengebrochen ist, werden die Validierungen nicht ausgelöst. Wie kann ich das beheben? Ich weiß, wenn ich mich für ein normales JQuery-Validierungs-Plugin anstelle von MVC3 entschieden hätte, musste ich sagen$('#form').validate({ignore: ""})
Parsh
1
Es hat bei mir in PHP funktioniert. Fügen Sie einfach diese Informationen hinzu, da jeder Kommentar auf .NET MVC verweist. : P
finnTheHumin
42

Ich mag die Einfachheit der @ viggity- und @ Robins-Lösung wirklich sehr, deshalb habe ich daraus ein schnelles kleines Plugin gemacht:

(function ($) {

    $.fn.updateValidation = function () {
        var $this = $(this);
        var form = $this.closest("form")
            .removeData("validator")
            .removeData("unobtrusiveValidation");

        $.validator.unobtrusive.parse(form);

        return $this;
    };
})(jQuery);

Anwendungsbeispiel:

$("#DischargeOutcomeNumberOfVisits")
    .attr("data-val-range-min", this.checked ? "1" : "2")
    .updateValidation();
Lambinator
quelle
Ersetzen Sie $ .validator.unobtrusive.parse ("#" + form.attr ("id")); mit $ .validator.unobtrusive.parse (Formular);
Softlion
Sie können .first () auch sicher entfernen, da next nur 1 Element zurückgibt.
Softlion
Schön, ich mag diesen einfachen Ansatz
Nixon
Funktioniert
hervorragend
33

Ich habe das gleiche Problem. Ich habe festgestellt, dass es nicht möglich ist, $ .validator.unobtrusive.parse () zweimal im selben Formular aufzurufen. Beim erstmaligen Laden des Formulars vom Server wird das Formular automatisch von der unauffälligen Bibliothek analysiert. Wenn Sie dem Formular dynamisch ein Eingabeelement hinzufügen und $ .validator.unobtrusive.parse () erneut aufrufen, funktioniert dies nicht. Gleiches gilt für parseElement ().

Die unauffällige lib ruft die validate-Methode des jquery validate-Plugins auf, um alle Regeln und Nachrichten festzulegen. Das Problem ist, dass das Plugin beim erneuten Aufruf die angegebenen neuen Regeln nicht aktualisiert.

Ich habe eine grobe Lösung gefunden: Bevor ich die Analysemethode für die unauffällige Bibliothek aufrufe, werfe ich den Formularvalidator weg:

$('yourForm').removeData("validator");

Wenn nun die Validierungsmethode von der unauffälligen Bibliothek aufgerufen wird, werden alle Regeln und Nachrichten einschließlich der dynamisch hinzugefügten Eingaben neu erstellt.

Hoffe das hilft

Robin van der Knaap
quelle
Verdient eine +1 - es ist eine grobe Lösung, wie Sie selbst gesagt haben, aber es ist ziemlich klar, was es tut und in welchem ​​Zustand Sie danach bleiben
Per Hornshøj-Schierbeck
2
Aus Brad Wilsons Blog: "Sie können auch die Funktion jQuery.validator.unobtrusive.parseElement () aufrufen, um ein einzelnes HTML-Element zu analysieren." Irgendeine Hilfe?
Jamesfm
@Per Hornshøj-Schierbeck: @Robin van der Knaap: Ich habe die letzten 2-3 Stunden damit verbracht, das herauszufinden !! Wie auch immer - das hat wunderbar funktioniert. Bei Rohöl habe ich das Gefühl, ich sollte es nicht verwenden - warum sollte ich das nicht tun wollen?
KTF
2
Die Lösung ist etwas grob, da alle Validatoren entfernt und wieder hergestellt werden, einschließlich des dynamisch hinzugefügten Validators. Es wäre besser, wenn nur der dynamisch hinzugefügte Validator aktualisiert würde. @Xhalent bietet in seiner Antwort eine sauberere Lösung, aber im Grunde sollte die unauffällige Bibliothek von MS für dieses Szenario aktualisiert werden.
Robin van der Knaap
9

Ich verwende MVC 4 und JQuery 1.8. Es sieht so aus, als ob der folgende Code benötigt wird, damit Jquery dynamisch injizierten Inhalt über Ajax oder Jquery in das DOM validieren kann.

Ich habe eine modulare Funktion erstellt, die das Jquery-Objekt des neu hinzugefügten Elements akzeptiert. Wenn Sie tblContactsmit Jquery auf Knopfdruck eine neue Tabelle mit der ID geklont haben , fügen Sie die folgende Funktion in Ihre js-Datei ein

function fnValidateDynamicContent(element) {
    var currForm = element.closest("form");
    currForm.removeData("validator");
    currForm.removeData("unobtrusiveValidation");
    $.validator.unobtrusive.parse(currForm);
    currForm.validate(); // This line is important and added for client side validation to trigger, without this it didn't fire client side errors.
}

und nenne es so:

fnValidateDynamicContent("#tblContacts")
Sundara Prabu
quelle
currform.validate (); sollte eigentlich currForm.validate () sein; (Tippfehler). Vielen Dank für das Teilen, das hat bei mir funktioniert
John Mc
1
@ JohnMc hat den Tippfehler jetzt
behoben
Dies ist die einzige, die für mich gearbeitet hat (MVC 4 und JQuery 1.10)
The Muffin Man
4

Verwenden Sie die Regelfunktion direkt aus dem jquery-Validierungsdokument. So was:

$('#newField0').rules('add', {
    required: true,
    minlength: 2
});
//use Html.ValidationMessage will renders a span element, unobtrusive need it to display errors
$('@Html.ValidationMessage("newField0")').insertAfter('#newField0');
zhangfx
quelle
2

Ausgehend von Xhalents Lösung, die oben als Antwort markiert wurde, habe ich sie etwas erweitert.

$.validator.unobtrusive.parseDynamicContent = function (selector) {
    var $selector = $(selector),
        $jqValUnob = $.validator.unobtrusive,
        selectorsDataValAttr = $selector.attr('data-val'),
        $validationInputs = $selector.find(':input[data-val=true]');

    if ((selectorsDataValAttr !== 'true') && 
        ($validationInputs.length === 0)) { 
        return; 
    }

    if (selectorsDataValAttr === 'true') {
        $jqValUnob.parseElement(selector, true);
    }

    $validationInputs.each(function () {
        $jqValUnob.parseElement(this, true);
    });

    //get the relevant form
    var $form = $selector.first().closest('form');

    $jqValUnob.syncValdators($form);
};

/* synchronizes the unobtrusive validation with jquery validator */
$.validator.unobtrusive.syncValdators = function ($form) {
    if ($.hasData($form[0])) {
        var unobtrusiveValidation = $form.data('unobtrusiveValidation'),
            validator = $form.validate();

        // add validation rules from unobtrusive to jquery
        $.each(unobtrusiveValidation.options.rules, function (elname, elrules) {
            if (validator.settings.rules[elname] == undefined) {
                var args = {};
                $.extend(args, elrules);
                args.messages = unobtrusiveValidation.options.messages[elname];
                $("[name='" + elname + "']").rules("add", args);
            } else {
                $.each(elrules, function (rulename, data) {
                    if (validator.settings.rules[elname][rulename] == undefined) {
                        var args = {};
                        args[rulename] = data;
                        args.messages = unobtrusiveValidation.options.messages[elname][rulename];
                        $("[name='" + elname + "']").rules("add", args);
                    }
                });
            }
        });
        // remove all validation rules from jquery that arn't in unobtrusive
        $.each(validator.settings.rules, function (elname, elrules) {
            if (unobtrusiveValidation.options.rules[elname] === undefined) {
                delete validator.settings.rules[elname];
            } else {
                $.each(elrules, function (rulename, data) {
                    if (rulename !== "messages" && unobtrusiveValidation.options.rules[elname][rulename] === undefined) {
                        delete validator.settings.rules[elname][rulename];
                    }
                });
            }
        });
    }        
};

$.validator.unobtrusive.unparseContent = function (selector) {
    var $selector = $(selector);

    // if its  a text node, then exit
    if ($selector && $selector.length > 0 && $selector[0].nodeType === 3) {
        return;
    }

    var $form = $selector.first().closest('form'), 
        unobtrusiveValidation = $form.data('unobtrusiveValidation');

    $selector.find(":input[data-val=true]").each(function () {
        removeValidation($(this), unobtrusiveValidation);
    });
    if ($selector.attr('data-val') === 'true') {
        removeValidation($selector, unobtrusiveValidation);
    }
    $.validator.unobtrusive.syncValdators($form);
};

function removeValidation($element, unobtrusiveValidation) {
    var elname = $element.attr('name');
    if (elname !== undefined) {
        $element.rules('remove');
        if (unobtrusiveValidation) {
            if (unobtrusiveValidation.options.rules[elname]) {
                delete unobtrusiveValidation.options.rules[elname];
            }
            if (unobtrusiveValidation.options.messages[elname]) {
                delete unobtrusiveValidation.options.messages[elname];
            }
        }
    }
}

Im Grunde funktioniert es immer noch genauso wie die obige Xhalent-Lösung, aber ich habe die Möglichkeit hinzugefügt, Regeln für Elemente zu entfernen, die Sie aus dem Dom entfernen. Wenn Sie also Elemente aus dem Dom entfernen und möchten, dass diese Validierungsregeln ebenfalls entfernt werden, rufen Sie Folgendes auf:

$.validator.unobtrusive.unparseContent('input.something');
Evan Larsen
quelle
1

Ich habe das Codeskript von @ Xhalent in meinem Code gefunden und wollte es löschen, weil ich es nicht verwendet habe, was mich zu dieser SO-Frage führte.

Dieser Code ist ziemlich sauber und einfach:

jQuery.fn.unobtrusiveValidationForceBind = function () {
    //If you try to parse a form that is already parsed it won't update
    var $form = this
       .removeData("validator") /* added by the raw jquery.validate plugin */
            .removeData("unobtrusiveValidation");  /* added by the jquery     unobtrusive plugin */

    $form.bindUnobtrusiveValidation();
}

Um diese jQuery-Erweiterung aufzurufen, verwenden Sie einfach einen Selektor, um Ihr Formular abzurufen:

$('#formStart').unobtrusiveValidationForceBind();

Viola!

Brian Ogden
quelle
1

Ich versuchte es mit der Antwort von Viggity und zuerst schien alles zu funktionieren. Aber nach einer Weile bemerkte ich, dass die Validierung umso schmerzhafter wird, je dynamischer die Elemente sind, die ich hinzugefügt habe. Der Grund war, dass seine Lösung die Ereignishandler nicht auflöst, sondern jedes Mal neue hinzufügt. Wenn Sie also 5 Elemente hinzufügen, wird die Validierung 6-mal statt nur einmal ausgeführt. Um dies zu beheben, müssen Sie die Ereignisse zusätzlich zu den removeData-Aufrufen aufheben.

$("form").removeData("validator")
         .removeData("unobtrusiveValidation")
         .off("submit.validate click.validate focusin.validate focusout.validate keyup.validate invalid-form.validate");
$.validator.unobtrusive.parse("form");
Benedikt Langer
quelle
1

Bei dynamischen Inhalten müssen Sie die unauffälligen Überprüfungen wie Formfolgt aktualisieren und beim Senden überprüfen, ob sie gültig sind.

function UpdateUnobtrusiveValidations(idForm) {
    $(idForm).removeData("validator").removeData("unobtrusiveValidation");
    $.validator.unobtrusive.parse($(idForm));
};


$('#idDivPage').on('click', '#idSave', function (e) {
    e.preventDefault();
    if (!$('#idForm').valid()) {
        // Form is invalid … so return
        return false;
    }
    else {
        // post data to server using ajax call
        // update Unobtrusive Validations again
        UpdateUnobtrusiveValidations('#idForm');
    }
});
Jagdeesh Motegowda
quelle
0

Ich habe eine Weile damit herumgespielt, Lösungen verschrottet und es später erneut versucht (wenn ich etwas Freizeit hatte, ob Sie es glauben oder nicht).

Ich bin nicht sicher, ob sich dieses Verhalten in neueren Versionen von jquery (wir verwenden 1.7.2) geändert hätte, seit dieser Thread zuletzt erstellt oder kommentiert wurde, aber ich fand, dass dies gut .parseElement(inputElement)funktioniert, wenn ich versuche, einem Formular dynamisch erstellte Elemente hinzuzufügen das hat schon einen validator geladen. Dies wurde bereits von @jamesfm (15. Februar 11) in einem der obigen Kommentare vorgeschlagen, aber ich habe es die ersten Male übersehen, als ich daran arbeitete. Deshalb füge ich es als separate Antwort hinzu, um es offensichtlicher zu machen, und weil ich denke, dass es eine gute Lösung ist und nicht so viel Aufwand erfordert. Es ist möglicherweise nicht für alle in den nachfolgenden Antworten aufgeworfenen Fragen relevant, aber ich denke, es wäre eine Lösung für die ursprüngliche Frage. So habe ich meine zum Laufen gebracht:

//row & textarea created dynamically by an async ajax call further up in the code
var row = ...; //row reference from somewhere
var textarea = row.find("textarea");
textarea.val("[someValue]");

//add max length rule to the text area
textarea.rules('add', {
    maxlength: 2000
});
//parse the element to enable the validation on the dynamically added element
$.validator.unobtrusive.parseElement(textarea);
Ben
quelle
0

Erstens denke ich, der Aufruf sollte an .validator erfolgen, nicht an validieren, dann müssen Sie die ID des Formulars übergeben

$.validator.unobtrusive.parse("#id");
Chris Allmark
quelle
Ich gehe davon aus, dass Sie die Skripte jquery.validate und jquery.validate.unobtrusive geladen und die Methoden Html.EnableClientValidation () und Html.EnableUnobtrusiveJavaScript () aufgerufen haben. Können Sie vielleicht ein Codebeispiel für Ihre Basisseite und das dynamisch geladene Formular veröffentlichen?
Chris Allmark
0

Wenn Sie Dinge hinzufügen und entfernen müssen, bei denen möglicherweise bereits einige Fehler angezeigt werden, habe ich Folgendes mitgebracht. Es basiert hauptsächlich auf verschiedenen Ideen auf dieser Fragenseite. Ich verwende das integrierte destroy()Attribut, anstatt nur das Datenattribut für die JQuery-Validierung zu entfernen.

function resetValidator($form: JQuery) {
    $form.validate().destroy();

    //reset unobtrusive validation summary, if it exists
    $form.find("[data-valmsg-summary=true]")
        .removeClass("validation-summary-errors")
        .addClass("validation-summary-valid")
        .find("ul").empty();

    //reset unobtrusive field level, if it exists
    $form.find("[data-valmsg-replace]")
        .removeClass("field-validation-error")
        .addClass("field-validation-valid")
        .empty();

    $form.removeData("unobtrusiveValidation");
}

Sie rufen es auf, bevor Sie die Eingaben im Formular dynamisch ändern. Anschließend initialisieren Sie die Validierung erneut.

resetValidator($form);
//add or remove inputs here ...
$.validator.unobtrusive.parse($form);

Hinweis: Wenn einige oder alle Eingaben validiert wurden und Fehler aufweisen, werden diese Fehler zurückgesetzt ... aber sie werden bei der nächsten Validierung korrekt wiedergegeben.

Yepeekai
quelle