客户端验证 - 至少一个组的复选框

时间:2018-04-10 14:42:25

标签: asp.net-mvc checkbox custom-data-attribute required

这里不习惯提问,但第一次就是一切。

我目前正在使用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">

先谢谢!

0 个答案:

没有答案