jquery.validate.unobtrusive不使用动态注入元素

时间:2010-12-10 06:27:41

标签: asp.net-mvc-3 jquery-validate unobtrusive-validation

我正在使用ASP.Net MVC3,使用客户端验证的更简单方法是启用jquery.validate.unobtrusive。对于那些来自服务器的东西,一切正常。

但是当我尝试用javascript注入一些新的'输入'时,我知道我需要调用$.validator.unobtrusive.parse()来重新绑定验证。但是,所有这些动态注入的字段都不起作用。

更糟糕的是,我尝试使用jquery.validate手动绑定,但它也无法正常工作。有什么想法吗?

13 个答案:

答案 0 :(得分:153)

我尝试过Xhalent的方法,但遗憾的是它不适合我。罗宾的方法确实有效,但没有奏效。它适用于动态添加的元素,但如果您尝试使用JQuery从DOM中删除所有验证属性和跨度,验证库仍会尝试验证它们。

但是,如果除了“validationData”之外还删除了表单的“unobtrusiveValidation”数据,它就像一个动态添加和删除您想要验证或未经验证的元素的魅力。

$("form").removeData("validator");
$("form").removeData("unobtrusiveValidation");
$.validator.unobtrusive.parse("form");

答案 1 :(得分:66)

我为jquery.validate.unobtrusive库创建了一个扩展,为我的情况解决了这个问题 - 它可能很有用。

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

答案 2 :(得分:39)

我实际上非常喜欢@viggity和@Robins解决方案的简单性,所以我把它变成了一个快速的小插件:

(function ($) {

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

        $.validator.unobtrusive.parse(form);

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

使用示例:

$("#DischargeOutcomeNumberOfVisits")
    .attr("data-val-range-min", this.checked ? "1" : "2")
    .updateValidation();

答案 3 :(得分:32)

我遇到了同样的问题。我发现不可能在同一个表单上调用$ .validator.unobtrusive.parse()两次。 最初从服务器加载表单时,表单由不显眼的库自动解析。当您将一个输入元素动态添加到窗体并再次调用$ .validator.unobtrusive.parse()时,它将无法正常工作。 parseElement()也是如此。

不显眼的lib调用jquery validate插件的validate方法来设置所有规则和消息。问题是,再次调用时,插件不会更新给定的新规则集。

我找到了一个粗略的解决方案:在不显眼的lib上调用parse方法之前,我扔掉了表单验证器:

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

现在,当不显眼的lib调用validate方法时,将重新创建所有规则和消息,包括动态添加的输入。

希望这有帮助

答案 4 :(得分:8)

我正在使用 MVC 4和JQuery 1.8,看起来需要以下代码才能使Jquery通过Ajax或Jquery验证动态注入的内容到DOM中。

我已经创建了一个模块化函数,它接受新添加元素的Jquery对象。 如果您在单击按钮时使用Jquery克隆了一个标识为tblContacts的新表,则将以下函数包含在您的js文件中

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.
}

并将其称为:

fnValidateDynamicContent("#tblContacts")

答案 5 :(得分:2)

根据上面回答的Xhalent解决方案,我稍微扩展了一下。

$.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];
            }
        }
    }
}

所以基本上它仍然与上面的Xhalent解决方案一样,但我添加了删除从dom中删除的元素的规则的能力。因此,当您从Dom中删除元素并且您希望删除这些验证规则时,请调用:

$.validator.unobtrusive.unparseContent('input.something');

答案 6 :(得分:2)

为什么不直接从jquery验证doc使用the rules function。像这样:

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

答案 7 :(得分:1)

我在我的代码中找到了@Xhalent的代码脚本,并且要删除它,因为我没有使用它,这引出了我的问题。

这段代码很简洁:

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

然后,要调用此jQuery扩展,只需使用选择器来获取表单:

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

中提琴!

答案 8 :(得分:1)

如果是动态内容,您需要更新Unobtrusive Validations,如下所示,并在提交时检查Form是否有效。

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

答案 9 :(得分:1)

我尝试了轻松的回答,起初一切似乎都有效。但过了一段时间后,我注意到验证变得非常缓慢,我添加的动态项目越多。原因是他的解决方案并没有取消绑定事件处理程序,而是每次都添加新的处理程序。因此,如果添加5个项目,验证将执行6次而不是仅执行一次。要解决此问题,您必须另外解除对removeData调用的绑定事件。

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

答案 10 :(得分:0)

首先,我认为调用应该是.validator,而不是验证然后你需要传入表单的id

$.validator.unobtrusive.parse("#id");

答案 11 :(得分:0)

我一直在摆弄这个问题一段时间,废弃解决方案并稍后再试(当我有空闲时间,信不信由你)。

我不确定这个行为是否会在较新版本的jquery(我们使用1.7.2)中发生变化,因为此线程最后创建或评论过,但我发现.parseElement(inputElement)在我尝试时工作正常将动态创建的元素添加到已加载验证程序的表单中。 @jamesfm(2011年2月15日)在上面的一条评论中已经提出过这个问题,但是我在最初的几次工作中忽略了这一点。所以我将它作为一个单独的答案添加,以使其更明显,因为我认为这是一个很好的解决方案,并不需要这么多的开销。它可能与后续答案中提出的所有问题无关,但我认为这将是原始问题的解决方案。以下是我的工作方式:

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

答案 12 :(得分:0)

如果您需要添加和删除内容(可能已经显示了一些错误),这就是我自带的。它主要基于此问题页面上的不同想法。我使用内置的destroy()而不是仅仅删除JQuery validate的data属性。

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

在动态修改表单中的输入之前,请先调用它。然后,您可以在之后重新初始化验证。

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

注意:如果某些或所有输入已经过验证并且有错误,那么这些错误将被重置...但是在下一次验证时它们将正确返回。