Использование require_from_group
из команды jquery-validation:
jQuery-validation Проект имеет подпапку в папке src , которая называется Additional .Вы можете проверить это здесь .
В этой папке у нас есть много дополнительных методов проверки, которые не распространены, поэтому они не добавляются по умолчанию.
Как вы видите в этой папке, существует так много методов, которые вам нужно выбрать, выбрав, какой метод проверки вам действительно нужен.
Исходя из вашего вопроса, нужный метод проверки называется require_from_group
из дополнительной папки.Просто скачайте этот связанный файл, который находится здесь и поместите его в папку приложения Scripts
.
Документация этого метода объясняет это:
Позволяетвы говорите: «по крайней мере, X входов, которые соответствуют селектору Y, должны быть заполнены».
Конечным результатом является то, что ни один из этих входов:
... не будет проверен, если толькопо крайней мере один из них заполнен.
номер_партии: {require_from_group: [1, ". productinfo"]}, описание: {require_from_group: [1, ". productinfo"]}
опции[0]: количество полей, которые должны быть заполнены в параметрах группы 2 : селектор CSS, который определяет группу условно обязательных полей
Почему вам нужно выбрать эту реализацию:
Этот метод проверки является общим и работает для всех input
(текст, флажок, радио и т. Д.), textarea
и select
. Этот метод также позволяет указать минимальное количество обязательных входных данных, которые необходимо заполнить например,
partnumber: {require_from_group: [2,".productinfo"]},
category: {require_from_group: [2,".productinfo"]},
description: {require_from_group: [2,".productinfo"]}
Я создал два класса RequireFromGroupAttribute
и RequireFromGroupFieldAttribute
, которые помогут вам в обоихпроверки на стороне сервера и на стороне клиента
RequireFromGroupAttribute
определение класса
RequireFromGroupAttribute
происходит только от Attribute
.Класс используется только для настройки, например, для установки количества полей, которые необходимо заполнить для проверки.Вы должны предоставить этому классу CSS-класс селектора, который будет использоваться методом проверки для получения всех элементов в одной группе.Поскольку количество обязательных полей по умолчанию равно 1, этот атрибут используется только для украшения вашей модели, если минимальное требование в группе spcefied больше номера по умолчанию.
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class RequireFromGroupAttribute : Attribute
{
public const short DefaultNumber = 1;
public string Selector { get; set; }
public short Number { get; set; }
public RequireFromGroupAttribute(string selector)
{
this.Selector = selector;
this.Number = DefaultNumber;
}
public static short GetNumberOfRequiredFields(Type type, string selector)
{
var requiredFromGroupAttribute = type.GetCustomAttributes<RequireFromGroupAttribute>().SingleOrDefault(a => a.Selector == selector);
return requiredFromGroupAttribute?.Number ?? DefaultNumber;
}
}
RequireFromGroupFieldAttribute
определение класса
RequireFromGroupFieldAttribute
, которое происходит от ValidationAttribute
и реализует IClientValidatable
.Вам нужно использовать этот класс для каждого свойства вашей модели, которое участвует в проверке вашей группы.Вы должны передать класс селектора css.
[AttributeUsage(AttributeTargets.Property)]
public class RequireFromGroupFieldAttribute : ValidationAttribute, IClientValidatable
{
public string Selector { get; }
public bool IncludeOthersFieldName { get; set; }
public RequireFromGroupFieldAttribute(string selector)
: base("Please fill at least {0} of these fields")
{
this.Selector = selector;
this.IncludeOthersFieldName = true;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var properties = this.GetInvolvedProperties(validationContext.ObjectType); ;
var numberOfRequiredFields = RequireFromGroupAttribute.GetNumberOfRequiredFields(validationContext.ObjectType, this.Selector);
var values = new List<object> { value };
var otherPropertiesValues = properties.Where(p => p.Key.Name != validationContext.MemberName)
.Select(p => p.Key.GetValue(validationContext.ObjectInstance));
values.AddRange(otherPropertiesValues);
if (values.Count(s => !string.IsNullOrWhiteSpace(Convert.ToString(s))) >= numberOfRequiredFields)
{
return ValidationResult.Success;
}
return new ValidationResult(this.GetErrorMessage(numberOfRequiredFields, properties.Values), new List<string> { validationContext.MemberName });
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var properties = this.GetInvolvedProperties(metadata.ContainerType);
var numberOfRequiredFields = RequireFromGroupAttribute.GetNumberOfRequiredFields(metadata.ContainerType, this.Selector);
var rule = new ModelClientValidationRule
{
ValidationType = "requirefromgroup",
ErrorMessage = this.GetErrorMessage(numberOfRequiredFields, properties.Values)
};
rule.ValidationParameters.Add("number", numberOfRequiredFields);
rule.ValidationParameters.Add("selector", this.Selector);
yield return rule;
}
private Dictionary<PropertyInfo, string> GetInvolvedProperties(Type type)
{
return type.GetProperties()
.Where(p => p.IsDefined(typeof(RequireFromGroupFieldAttribute)) &&
p.GetCustomAttribute<RequireFromGroupFieldAttribute>().Selector == this.Selector)
.ToDictionary(p => p, p => p.IsDefined(typeof(DisplayAttribute)) ? p.GetCustomAttribute<DisplayAttribute>().Name : p.Name);
}
private string GetErrorMessage(int numberOfRequiredFields, IEnumerable<string> properties)
{
var errorMessage = string.Format(this.ErrorMessageString, numberOfRequiredFields);
if (this.IncludeOthersFieldName)
{
errorMessage += ": " + string.Join(", ", properties);
}
return errorMessage;
}
}
Как использовать его в вашей модели представления?
В вашей модели вот как его использовать:
public class SomeViewModel
{
internal const string GroupOne = "Group1";
internal const string GroupTwo = "Group2";
[RequireFromGroupField(GroupOne)]
public bool IsA { get; set; }
[RequireFromGroupField(GroupOne)]
public bool IsB { get; set; }
[RequireFromGroupField(GroupOne)]
public bool IsC { get; set; }
//... other properties
[RequireFromGroupField(GroupTwo)]
public bool IsY { get; set; }
[RequireFromGroupField(GroupTwo)]
public bool IsZ { get; set; }
}
По умолчанию вам не нужно украшать вашу модель RequireFromGroupAttribute
, потому что количество обязательных полей по умолчанию равно 1. Но если вы хотите, чтобы количество обязательных полей отличалось от 1, вы можете сделать следующее:
[RequireFromGroup(GroupOne, Number = 2)]
public class SomeViewModel
{
//...
}
Как использовать его в вашем коде представления?
@model SomeViewModel
<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/require_from_group.js")" type="text/javascript"></script>
@using (Html.BeginForm())
{
@Html.CheckBoxFor(x => x.IsA, new { @class="Group1"})<span>A</span>
@Html.ValidationMessageFor(x => x.IsA)
<br />
@Html.CheckBoxFor(x => x.IsB, new { @class = "Group1" }) <span>B</span><br />
@Html.CheckBoxFor(x => x.IsC, new { @class = "Group1" }) <span>C</span><br />
@Html.CheckBoxFor(x => x.IsY, new { @class = "Group2" }) <span>Y</span>
@Html.ValidationMessageFor(x => x.IsY)
<br />
@Html.CheckBoxFor(x => x.IsZ, new { @class = "Group2" })<span>Z</span><br />
<input type="submit" value="OK" />
}
Обратите внимание, что селектор группы, указанный вами при использовании атрибута RequireFromGroupField
, используется в вашем представлении, указав его как класс в каждом задействованном входев ваших группах.
Это все для проверки на стороне сервера.
Давайте поговорим о проверке на стороне клиента.
Если вы проверите реализацию GetClientValidationRules
в классе RequireFromGroupFieldAttribute
, вы увидите, что я использую строку requirefromgroup
, а не require_from_group
как имя метода для свойства ValidationType
.Это связано с тем, что ASP.Net MVC позволяет только имени типа проверки содержать буквенно-цифровой символ и не должен начинаться с цифры.Поэтому вам нужно добавить следующий javascript:
$.validator.unobtrusive.adapters.add("requirefromgroup", ["number", "selector"], function (options) {
options.rules["require_from_group"] = [options.params.number, options.params.selector];
options.messages["require_from_group"] = options.message;
});
Часть javascript действительно проста, потому что при реализации функции адаптера мы просто делегируем проверку правильному методу require_from_group
.
Поскольку он работает с каждым типом элементов input
, textarea
и select
, я могу подумать, что этот способ является более общим.
Надеюсь, что это поможет!