3

さて、製品のチェックボックスがあり、少なくとも 1 つの製品が選択されていることを確認したいと思います。

これを行うために、私の ViewModel には以下が含まれています。

[DisplayName(@"Product Line")]
[MinChecked(1)]
public List<CheckboxInfo> ActiveProducts { get; set; }

ビューには次のものが含まれます。

@Html.EditorFor(x => x.ActiveProducts)

その EditorTemplate には以下が含まれます。

@model Rad.Models.CheckboxInfo

@Html.HiddenFor(x => x.Value)
@Html.HiddenFor(x => x.Name)
@Html.CheckBoxFor(x => x.Selected)
@Html.LabelFor(x => x.Selected, Model.Name)

カスタム データ注釈は次のとおりです。

[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class MinCheckedAttribute : ValidationAttribute, IClientValidatable
{
    public int MinValue { get; set; }

    public MinCheckedAttribute(int minValue)
    {
        MinValue = minValue;
        ErrorMessage = "At least " + MinValue + " {0} needs to be checked.";
    }

    public override string FormatErrorMessage(string propName)
    {
        return string.Format(ErrorMessage, propName);
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        try
        {
            List<CheckboxInfo> valueList = (List<CheckboxInfo>)value;
            foreach (var valueItem in valueList)
            {
                if (valueItem.Selected)
                {
                    return ValidationResult.Success;
                }
            }
            return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
        }
        catch (Exception x)
        {
            return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
        }
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var rule = new ModelClientValidationRule
        {
            ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()),
            ValidationType = "minchecked",
        };

        rule.ValidationParameters["minvalue"] = MinValue;

        yield return rule;
    } 
}

jQuery の部分は次のとおりです。

$.validator.addMethod('minchecked', function (value, element, params) {
    var minValue = params['minvalue'];
    alert(minValue);
    $(element).each(function () {
        if ($(this).is(':checked')) {
            return true;
        }
    });
    return false;
});
$.validator.unobtrusive.adapters.add('minchecked', ['minvalue'], function (options) {
    options.messages['minchecked'] = options.message;
    options.rules['minchecked'] = options.params;
});

したがって、検証はサーバー側で機能します。

しかし、目立たない検証を機能させるにはどうすればよいですか? 何らかの理由で、

GetClientValidationRulesHTML5をチェックボックスに添付していません。

4

1 に答える 1

1

上記と非常によく似た実装があり、このクライアント側のjqueryコードは、モデルの一部であるチェックボックスのグループに対して機能します(HTML5に添付されます)。データ注釈から ErrorMessage を転送します。

    [Display(Name = "Location1")]
    [CheckAtLeastOne(ErrorMessage = "Must check at least one Location")]
    public DateTime Location1 { get; set; }

    [Display(Name = "Location2")]
    public DateTime Location2 { get; set; }

    [Display(Name = "Location3")]
    public DateTime Location3 { get; set; }

    [Display(Name = "Location4")]
    public DateTime Location4 { get; set; }

    $(function () {
    $.validator.addMethod("checkatleastone", function (value, element) {
        var tag = $("#editform-locations").find(":checkbox");
        return tag.filter(':checked').length;
    });
});
$.validator.unobtrusive.adapters.addBool("checkatleastone");

ただし、私の場合、モデルの一部ではないチェックボックスの別のコレクションがあります。これは別のテーブルであるため、チェックボックスのリストを生成するために使用される Viewbag に入力されます。サーバー側は機能しませんが、クライアント側の検証は、この jquery を使用し、一致するクラス名をチェックボックスの html に追加することで機能します。

    $(function () {
    $.validator.addMethod("CheckOneCategory", function (value, element) {
        var tag = $("#editform-categories").find(":checkbox");
        return tag.filter(':checked').length;
    }, "Select at least one Product/Service Category");
    $.validator.addClassRules("require-one-category", { CheckOneCategory: true });
});
于 2013-02-27T18:50:23.277 に答える