这里不习惯提问,但第一次就是一切。
我目前正在使用ASP.NET MVC中的一个Web项目,而我却陷入了第一种形式...... 我要做的是显示一组复选框,并要求至少检查其中一个复选框。幸运的是,我已经在这个问题上找到了几个答案,它只能在服务器端运行。
但我无法弄清楚为什么它不能在客户端工作!虽然我的所有其他字段自定义规则都适用于客户端! 我仍然对这项技术很陌生,所以也许我在这里错过了一些东西......
我已经好几天了。我希望有人能够帮助我。
以下是关于复选框的代码:
查看
<div class="col-sm-3">
<label>Documents:<br/>(select at least one)*</label><br/>
@Html.ValidationMessageFor(m => m.AllDocumentsChecked, "", new @class = "text-danger" })
</div>
<div class="col-sm-3">
<div class="form-check">
@Html.CheckBoxFor(m => m.AllDocumentsChecked, new { @class = "form-check-input", @id = "AllDocumentsChecked", @name = "outputFiles" })
<label for="select_all" class="form-check-label">All Documents</label>
</div>
<div class="form-check">
@Html.CheckBoxFor(m => m.Doc1Checked, new { @class = "form-check-input check", @id = "Doc1Checked", @name = "outputFiles" })
<label for="file_doc1" class="form-check-label">Doc1</label>
</div>
<div class="form-check">
@Html.CheckBoxFor(m => m.Doc2Checked, new { @class = "form-check-input check", @id = "Doc2Checked", @name = "outputFiles" })
<label for="file_doc2" class="form-check-label">Doc2</label>
</div>
</div>
<div class="col-sm-3">
<div class="form-check">
@Html.CheckBoxFor(m => m.Doc3Checked, new { @class = "form-check-input check", @id = "Doc3Checked", @name = "outputFiles" })
<label for="file_doc3" class="form-check-label">Doc3</label>
</div>
<div class="form-check">
@Html.CheckBoxFor(m => m.Doc4Checked, new { @class = "form-check-input check", @id = "Doc4Checked", @name = "outputFiles" })
<label for="file_doc4" class="form-check-label">Doc4</label>
</div>
<div class="form-check">
@Html.CheckBoxFor(m => m.Doc5Checked, new { @class = "form-check-input check", @id = "Doc5Checked", @name = "outputFiles" })
<label for="file_doc5" class="form-check-label">Doc5</label>
</div>
</div>
<div class="col-sm-3">
<div class="form-check">
@Html.CheckBoxFor(m => m.Doc6Checked, new { @class = "form-check-input check", @id = "Doc6Checked", @name = "outputFiles" })
<label for="file_doc6" class="form-check-label">Doc6</label>
</div>
</div>
模型
[Display(Name = "All Documents")]
[RequireAtLeastOneOfGroup("Documents")]
public bool AllDocumentsChecked { get; set; }
[Display(Name = "Doc1")]
[RequireAtLeastOneOfGroup("Documents")]
public bool Doc1Checked { get; set; }
[Display(Name = "Doc2")]
[RequireAtLeastOneOfGroup("Documents")]
public bool Doc2Checked { get; set; }
[Display(Name = "Doc3")]
[RequireAtLeastOneOfGroup("Documents")]
public bool Doc3Checked { get; set; }
[Display(Name = "Doc4")]
[RequireAtLeastOneOfGroup("Documents")]
public bool Doc4Checked { get; set; }
[Display(Name = "Doc5")]
[RequireAtLeastOneOfGroup("Documents")]
public bool Doc5Checked { get; set; }
[Display(Name = "Doc6")]
[RequireAtLeastOneOfGroup("Documents")]
public bool Doc6Checked { get; set; }
RequireAtLeastOneFromGroupAttribute class
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class RequireAtLeastOneOfGroupAttribute : ValidationAttribute, IClientValidatable
{
public string GroupName { get; private set; }
public RequireAtLeastOneOfGroupAttribute(string groupName)
{
ErrorMessage = string.Format("You must select at least one value from this group", groupName);
GroupName = groupName;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
foreach (var property in GetGroupProperties(validationContext.ObjectType))
{
var propertyValue = (bool)property.GetValue(validationContext.ObjectInstance, null);
if (propertyValue)
{
// at least one property is true in this group => the model is valid
return ValidationResult.Success;
}
}
return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
}
private IEnumerable<PropertyInfo> GetGroupProperties(Type type)
{
return
from property in type.GetProperties()
where property.PropertyType == typeof(bool)
let attributes = property.GetCustomAttributes(typeof(RequireAtLeastOneOfGroupAttribute), false).OfType<RequireAtLeastOneOfGroupAttribute>()
where attributes.Count() > 0
from attribute in attributes
where attribute.GroupName == GroupName
select property;
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var groupProperties = GetGroupProperties(metadata.ContainerType).Select(p => p.Name);
var rule = new ModelClientValidationRule
{
ErrorMessage = this.ErrorMessage
};
rule.ValidationType = string.Format("group", GroupName.ToLower());
rule.ValidationParameters.Add("group", string.Join(",", groupProperties));
//rule.ValidationParameters["propertynames"] = string.Join(",", groupProperties);
yield return rule;
}
}
require_at_least_one_from_group javascript
$.validator.unobtrusive.adapters.add('atleastone', ['propertynames'],
function (options) {
options.rules['group'] = { propertynames: options.params.propertynames.split(',') };
options.messages['group'] = options.message;
});
$.validator.addMethod('group',
function (value, element, params) {
var properties = params.properties.split(',');
var isValid = false;
for (var i = 0; i < properties.length; i++) {
var property = properties[i];
if ($('#' + property).is(':checked')) {
isValid = true;
break;
}
}
return isValid;
}, '');
修改
复选框的html标记示例
在上面的助手产生的html下面。仍然看不出有什么问题。
<input class="form-check-input check" data-val="true" data-val-atleastone="You must select at least one value from this group"
data-val-atleastone-group="AllDocumentsChecked,Doc1Checked,Doc2Checked,
Doc3Checked,Doc4Checked,Doc5Checked,Doc6Checked" data-val-required="The Doc1 field is required."
id="Doc1Checked" name="Doc1Checked" value="true" type="checkbox">
<input name="Doc1Checked" value="false" type="hidden">
先谢谢!