我参加聚会有点晚了(只有几年)仍然......
最合适的解决方案确实是创建一个CustomAttribute
,但不是给你很好的建议,我会告诉你如何去做。
自定义属性:
public class GroupRequiredAttribute : ValidationAttribute, IClientValidatable
{
private readonly string[] _serverSideProperties;
public GroupRequiredAttribute(params string[] serverSideProperties)
{
_serverSideProperties = serverSideProperties;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
if (_serverSideProperties == null || _serverSideProperties.Length < 1)
{
return null;
}
foreach (var input in _serverSideProperties)
{
var propertyInfo = validationContext.ObjectType.GetProperty(input);
if (propertyInfo == null)
{
return new ValidationResult(string.Format("unknown property {0}", input));
}
var propertyValue = propertyInfo.GetValue(validationContext.ObjectInstance, null);
if (propertyValue is string && !string.IsNullOrEmpty(propertyValue as string))
{
return null;
}
if (propertyValue != null)
{
return null;
}
}
return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelClientValidationRule
{
ErrorMessage = ErrorMessage,
ValidationType = "grouprequired"
};
rule.ValidationParameters["grouprequiredinputs"] = string.Join(",", this._serverSideProperties);
yield return rule;
}
}
ViewModel:仅在 viewModel 上装饰一个字段,如下所示:
[GroupRequired("Year", "Month", "Day", ErrorMessage = "Please enter your date of birth")]
public int? Year { get; set; }
public int? Month { get; set; }
public int? Day { get; set; }
Jquery:在我的情况下,您需要添加适配器,jquery.validate.unobtrusive.customadapters.js
或者在您注册适配器的任何地方添加适配器(您可以将其放在页面上,只需在不显眼的验证运行后执行)。
(function ($) {
jQuery.validator.unobtrusive.adapters.add('grouprequired', ['grouprequiredinputs'], function (options) {
options.rules['grouprequired'] = options.params;
options.messages['grouprequired'] = options.message;
});
}(jQuery));
jQuery.validator.addMethod('grouprequired', function (value, element, params) {
var inputs = params.grouprequiredinputs.split(',');
var values = $.map(inputs, function (input, index) {
var val = $('#' + input).val();
return val != '' ? input : null;
});
return values.length == inputs.length;
});
那应该这样做。
对于那些对它的作用感兴趣的人:在 C# 领域中,它会抓取字段的 id 并将它们粘合起来,,
并将其放入 Year 字段的自定义属性中。
HTML应该看起来像这样(如果它不调试 C# 属性):
<input class="tooltip form-control input dob--input-long" data-val="true" data-val-grouprequired="Please enter your date of birth" data-val-grouprequired-grouprequiredinputs="Year,Month,Day" name="Year" placeholder="YYYY" tabindex="" type="text" value="">
然后 Jquery 验证将它们拆分回 id 并检查它们是否都不为空,仅此而已。
您将希望以某种方式将字段标记为无效(现在它只会标记字段属性位于)最合适的解决方案恕我直言,将所有字段包装在带有类的容器中field-error-wrapper
,然后在加载 Jquery 验证后将以下内容添加到您的页面:
$.validator.setDefaults({
highlight: function (element) {
$(element).closest(".field-error-wrapper").addClass("input-validation-error");
},
unhighlight: function (element) {
$(element).closest(".field-error-wrapper").removeClass("input-validation-error");
}
});
它不会标记字段,而是标记容器,然后你可以编写你的 CSS,如果容器被标记,.input-validation-error
那么里面的所有字段都会变成红色。我想我在这里的工作已经完成了。
编辑:好的,所以似乎还有一个问题是字段未被标记,因为验证器认为日期和月份是有效的,它需要从父级中删除无效类,验证器首先标记无效字段然后取消标记有效,这导致验证不被突出显示,所以我改变了验证发生的顺序,我不建议全局覆盖它(因为我不确定它可能会产生什么灾难性的影响),只需将它粘贴到你有生日字段的页面上。
$(function () {
$.data($('form')[0], 'validator').settings.showErrors = function () {
if (this.settings.unhighlight) {
for (var i = 0, elements = this.validElements() ; elements[i]; i++) {
this.settings.unhighlight.call(this, elements[i], this.settings.errorClass, this.settings.validClass);
}
}
this.hideErrors();
for (var i = 0; this.errorList[i]; i++) {
var error = this.errorList[i];
this.settings.highlight && this.settings.highlight.call(this, error.element, this.settings.errorClass, this.settings.validClass);
this.showLabel(error.element, error.message);
}
if (this.errorList.length) {
this.toShow = this.toShow.add(this.containers);
}
if (this.settings.success) {
for (var i = 0; this.successList[i]; i++) {
this.showLabel(this.successList[i]);
}
}
this.toHide = this.toHide.not(this.toShow);
this.addWrapper(this.toShow).show();
};
});
希望这可以节省您一些时间。