来自我对add class to parent div if validation error occurs using jquery validation 的回答,因为我相信它为这个问题的现有答案增加了价值...
访问验证器设置
首要任务是修改表单验证器上的settings 对象。您可以通过以下任一方式执行此操作:
- 在为所有表单加载表单之前调用
jQuery.validator.setDefaults()
- 通过传入
.validate([options]) 上的选项来初始化表单时
- 通过在表单上使用
$("form").data("validator").settings 定位验证器对象进行初始化后
由于您使用的是 MVC,所以选项 #2 是不可能的,因为 unobtrusive-validation 将自动初始化表单。所以让我们继续使用选项 3 - 这里的目标只是能够自定义表单上的设置。
覆盖默认行为
我们要修改的默认方法是highlight 和unhighlight,它们将分别高亮无效字段或恢复高亮选项所做的更改。这是他们的默认行为according to the source code:
highlight: function( element, errorClass, validClass ) {
if ( element.type === "radio" ) {
this.findByName( element.name ).addClass( errorClass ).removeClass( validClass );
} else {
$( element ).addClass( errorClass ).removeClass( validClass );
}
},
unhighlight: function( element, errorClass, validClass ) {
if ( element.type === "radio" ) {
this.findByName( element.name ).removeClass( errorClass ).addClass( validClass );
} else {
$( element ).removeClass( errorClass ).addClass( validClass );
}
}
所以你在这里也有几个选择。
- 完全替换那些函数,自己写
- 包装这些函数并像往常一样调用它们,但在之前或之后添加您自己的自定义代码。
选项 1 - 替换批发
这条路线很简单。随便在里面写什么就行了。也许从源代码种子,也许做你自己的事情。
var valSettings = $("form").data("validator").settings
valSettings.highlight = function(element, errorClass, validClass) { ... }
valSettings.unhighlight = function(element, errorClass, validClass) { ... }
选项 2 - 包装函数
这不太麻烦,所以在大多数情况下可能更可取。
由于最终您将替换 valSettings.highlight 的值,因此您需要访问原始函数的干净原始版本。您可以保存自己的或从全局默认值中获取一个
// original highlight function
var highlightOriginal = $("form").data("validator").settings.highlight;
var highlightDefaults = $.validator.defaults.highlight
在包装 JavaScript 函数方面,有几个示例 here、here 和 here)。这是其中之一的解析示例,这将有助于在函数调用之间绑定 this 上下文,保留传递的参数的数量,并保留返回值:
function wrap(functionToWrap, beforeFunction) {
return function () {
var args = Array.prototype.slice.call(arguments),
beforeFunction.apply(this, args);
return functionToWrap.apply(this, args);
};
};
然后,您还必须快速定义在调用时要触发的任何其他行为。在这种情况下,让我们找到最接近元素的父 div 并像这样更新它的类:
function highlightDecorator(element, errorClass, validClass) {
$(element).closest("div").addClass(errorClass).removeClass(validClass);
}
总结一下 (看看我做了什么)
$(function () {
var valSettings = $("form").data("validator").settings
valSettings.highlight = wrap($.validator.defaults.highlight, highlightDecorator)
valSettings.unhighlight = wrap($.validator.defaults.unhighlight, unhighlightDecorator)
});
function wrap(functionToWrap, beforeFunction) {
return function () {
var args = Array.prototype.slice.call(arguments);
beforeFunction.apply(this, args);
return functionToWrap.apply(this, args);
};
};
function highlightDecorator(element, errorClass, validClass) {
$(element).closest("div").addClass(errorClass).removeClass(validClass);
}
function unhighlightDecorator(element, errorClass, validClass) {
$(element).closest("div").addClass(validClass).removeClass(errorClass);
}
所以当我们结合以上所有功能时,它应该看起来像这样:
Stack Snippets 和jsFiddle 中的工作演示
$(function () {
var valSettings = $("form").data("validator").settings
valSettings.highlight = wrap($.validator.defaults.highlight, highlightDecorator)
valSettings.unhighlight = wrap($.validator.defaults.unhighlight, unhighlightDecorator)
});
function wrap(functionToWrap, beforeFunction) {
return function () {
var args = Array.prototype.slice.call(arguments);
beforeFunction.apply(this, args);
return functionToWrap.apply(this, args);
};
};
function highlightDecorator(element, errorClass, validClass) {
$(element).closest("div").addClass(errorClass).removeClass(validClass);
}
function unhighlightDecorator(element, errorClass, validClass) {
$(element).closest("div").addClass(validClass).removeClass(errorClass);
}
input.input-validation-error {
border: solid 1px red;
}
.input-validation-error label {
color: red;
}
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.16.0/jquery.validate.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.6/jquery.validate.unobtrusive.min.js"></script>
<form action="/Person" method="post">
<div class="required">
<label for="Name">Name <em>*</em></label>
<input id="Name" name="Name" type="text" value=""
data-val="true" data-val-required="The Name field is required."/>
<span class="field-validation-valid"
data-valmsg-for="Name" data-valmsg-replace="true"></span>
</div>
<input type="submit" value="Save" />
</form>