101

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

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

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

4

13 回答 13

167

我尝试了 Xhalent 的方法,但不幸的是它对我不起作用。罗宾的方法确实奏效了,也没有奏效。它对于动态添加的元素非常有效,但是如果您尝试使用 JQuery 从 DOM 中删除所有验证属性和跨度,验证库仍然会尝试验证它们。

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

$("form").removeData("validator");
$("form").removeData("unobtrusiveValidation");
$.validator.unobtrusive.parse("form");
于 2011-04-25T20:41:09.097 回答
65

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

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

于 2011-01-24T01:29:08.213 回答
44

我真的很喜欢 @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();
于 2011-10-27T02:45:47.330 回答
34

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

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

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

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

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

希望这可以帮助

于 2011-01-18T00:09:37.460 回答
10

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

我制作了一个模块化函数,它接受新添加元素的 Jquery 对象。tblContacts如果您在单击按钮时使用 Jquery克隆了一个带有 id 的新表,则在您的 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")
于 2013-02-28T06:51:01.163 回答
4

为什么不直接使用 jquery 验证文档中的规则功能。像这样:

$('#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');
于 2014-03-07T08:45:45.080 回答
4

我尝试了 viggity 的回答,起初一切似乎都奏效了。但过了一会儿,我注意到我添加的动态项目越多,验证就越慢。原因是他的解决方案没有取消绑定事件处理程序,而是每次都添加新的。因此,如果您添加 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");
于 2016-02-10T08:51:28.243 回答
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');
于 2012-05-21T15:24:35.957 回答
1

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

我不确定此行为是否会在较新版本的 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);
于 2013-03-19T00:47:14.390 回答
1

我在我的代码中找到了@Xhalent 的代码脚本,并打算将其删除,因为我没有使用它,这导致我提出了这个 SO 问题。

这段代码非常干净和简单:

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

中提琴!

于 2015-10-10T03:56:34.657 回答
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');
    }
});
于 2015-10-28T05:56:04.503 回答
0

Firstly, I think the call should be to .validator, not validate then you need to pass in the id of the form

$.validator.unobtrusive.parse("#id");
于 2010-12-21T08:40:00.410 回答
0

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

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

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

于 2020-06-11T14:02:50.207 回答