asp.net-mvc-3 - 使用动态插入的元素,jquery.validate.unobtrusive 不起作用

我在使用ASP.Net MVC3,客户端验证的更容易方法是,启用jquery.validate.unobtrusive,一切正常。

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

时间:


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

我也有同样的问题,我发现不能在同一个表单上两次调用$.validator.unobtrusive.parse(),当从服务器开始加载表单时,表单自动解析,将输入元素动态添加到表单,并再次调用$.validator.unobtrusive.parse()时,它不能工作,对于parseElement()同样适用。

我找到了一个粗略的解决方案:


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

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


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

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


fnValidateDynamicContent("#tblContacts")


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


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

当从Dom中移除元素,并希望移除这些验证规则时,也调用:


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

为什么不直接从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');

我一直在摆弄它,放弃解决方案,稍后再试( 当我有空闲时间时,相信它) 。

我不确定这种行为是否会在更新版本的jquery ( 我们正在使用 1.7.2 ) 中更改,因为这个线程是最后创建或者注释的,但我发现在将动态创建的元素添加到已经加载了验证器的表单时 .parseElement(inputElement) 工作良好。 在上面的一个评论中,@jamesfm ( 15'11已经被推荐了,但我在前面的几次工作中忽略了它。 所以我将它作为一个单独的答案添加,让它更加明显,因为我认为它是一个好的解决方案,并且不需要太多的开销。 这可能与后续答案中的所有问题无关,但我认为它将是一个原始问题的解决方案。 下面是我的工作方式:


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

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


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

...