jquery.validate.unobtrusive不适用于动态注入的元素


99

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

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

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


1
如果您是从Google来到这里的,那么您可能正在寻找@Sundara Prabu的答案,因为其他被广泛支持的都是古老的。
松饼人2015年

Answers:


65

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

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


我想我应该把你的答案选为正确的答案。顺便说一句,您的库是否与最新的MVC RC兼容?还是他们解决了这个问题?
xandy 2011年

1
使用上面链接的代码时,请确保将其更新为在注释中包含该代码,否则可能会中断。具体来说,更改两条选择器行以对ID加上双引号。
Ryan O'Neill

1
经过一些调试,终于可以在我的方案中使它正常工作。似乎不应传入输入选择器,而应传入的父项或表单(由于对的调用)$.validator.unobtrusive.parse()。另外,它似乎仅添加新规则,而不选择更新现有规则?
lambinator 2011年

5
该答案至少应包含博客文章的内容。链接只有答案通常是关闭SO话题
利亚姆

8
尽管此答案已使用3年以上,但是如果您可以在此处,此网站上发布答案的主要部分,或者删除帖子的风险,将非常有帮助。请参阅FAQ,其中提到的答案“远远超过链接” '。如果愿意,您仍可以包括该链接,但仅作为“参考”。答案应该独立存在,不需要链接。
塔林

159

我尝试了Xhalent的方法,但不幸的是,它对我没有用。罗宾的方法行得通而且行不通。它对于动态添加的元素非常有用,但是,如果您尝试使用JQuery从DOM中删除所有验证属性和范围,则验证库仍将尝试对其进行验证。

但是,如果除“ validationData”之外还删除了表单的“ unobtrusiveValidation”数据,它就像一种用于动态添加和删除要验证或未验证的元素的超级按钮。

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

2
Xhalent最初也对我不起作用,然后我注意到应该将解析传递给新元素的容器,而不是元素本身-快速解决方案是传递整个表单而不是元素-然后像魅力一样运作。
PerHornshøj-Schierbeck

1
知道为什么说validator未定义吗?我同时引用了validation和validation.unobtrusive。验证有效,直到我调用这些代码
Shawn Mclean

4
谢谢。它适用于通过AJAX调用添加的ASP.MVC部分视图中添加到页面的内容。
Maksym Kozlenko

谢谢你的帮助。但是我遇到的一个问题是我在页面上使用手风琴,如果手风琴被折叠,则不会触发验证。我怎样才能解决这个问题?我知道我是否曾经去过普通的jquery验证插件,而不是不喜欢MVC3,我不得不说$('#form').validate({ignore: ""})
parsh 2013年

1
它在PHP中对我有用。只需添加此信息,因为每个注释都指向.NET MVC。:P
finnTheHumin 2014年

42

我实际上真的很喜欢@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();

替换$ .validator.unobtrusive.parse(“#” + form.attr(“ id”)); 与$ .validator.unobtrusive.parse(form);
Softlion

您也可以安全地删除.first(),因为最接近的元素仅返回1个元素。
Softlion

尼斯,我喜欢这种简单的方法
尼克松

添加和删​​除数据值属性的效果都很好
朱利安·多蒙

33

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

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

我找到了一个简单的解决方案:在不打扰的lib上调用parse方法之前,我丢弃了表单验证器:

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

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

希望这可以帮助


值得+1-这是一个粗略的解决方案,就像您自己说的那样,但是很清楚它的作用以及之后的剩余状态
PerHornshøj-Schierbeck'2

2
来自Brad Wilsons博客:“您还可以调用jQuery.validator.unobtrusive.parseElement()函数来解析单个HTML元素。” 有什么帮助吗?
jamesfm 2011年

@PerHornshøj-Schierbeck:@Robin van der Knaap:我花了最后的2-3个小时来解决这个问题!无论如何-这很了不起。粗鲁让我感到我不应该使用它-为什么我不想这样做?
KTF

2
解决方案有点粗糙,因为所有验证器(包括动态添加的验证器)都已删除并再次恢复。如果只更新动态添加的验证器,那会更好。@Xhalent在他的答案中提供了一个更干净的解决方案,但是基本上对于这种情况,应该更新MS的兼容库。
罗宾·凡德·纳纳普

9

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

我做了一个模块化的函数,可以接受新添加元素的Jquery对象。如果tblContacts单击按钮后使用Jquery 克隆了一个ID为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")

currform.validate(); 实际上应该是currForm.validate(); (典型)。不过感谢您的分享,这对我
有用

1
@JohnMc现在修复了错字
Sundara Prabu

这是唯一为我工作的工具(mvc 4和jquery 1.10)
The Muffin Man

4

为什么不直接从jquery验证文档中使用rules函数。像这样:

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

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

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

中提琴!


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

1

如果是动态内容,则需要如下更新“非侵入式验证”,并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');
    }
});

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

0

首先,我认为调用应该是.validator,而不是验证,那么您需要传递表单的ID

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

我假设您已加载了jquery.validate和jquery.validate.unobtrusive脚本,并分别调用了Html.EnableClientValidation()和Html.EnableUnobtrusiveJavaScript()方法?您可以为您的基本页面和动态加载的表单发布代码示例吗?
克里斯·奥尔马克

0

如果您需要添加和删除某些东西(可能已经显示了一些错误),这就是我自带的。它主要基于此问题页面上的不同想法。我使用内置方法,destroy()而不仅仅是删除JQuery验证的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);

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.