Ответ 1
Я немного опаздываю на вечеринку (всего пару лет)...
Наиболее подходящее решение действительно создает 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: Украсьте только одно поле в вашем представленииModel, как показано ниже:
[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;
});
и это должно быть сделано.
Для тех, кому это интересно: на С# land он захватывает идентификаторы полей, склеивает их с помощью ,
и помещает в пользовательский атрибут в поле Year.
HTML должен выглядеть примерно так (если он не отлаживает атрибут С#):
<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 и проверяет, не все ли они пустые и что в значительной степени это.
Вы хотите как-то пометить поля как некорректные (теперь это будет только отметить, что атрибут поля сидит) наиболее подходящее решение IMHO состоит в том, чтобы обернуть все поля в контейнере с классом 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();
};
});
Надеюсь, это сэкономит вам некоторое время.