11

我正在尝试对单选按钮列表进行必要的验证,以强制用户选择一个选项以继续。验证确实有效,但它仅在第一个单选按钮上输出元数据,并且仅使用类 input-validation-error 标记第一个单选按钮。

例子:

<p>@Html.RadioButtonFor(x => x.Choices, SomeEnum.OptionOne)</p>
<p>@Html.RadioButtonFor(x => x.Choices, SomeEnum.OptionTwo)</p>

生成的 HTML:

<p><input class="input-validation-error" data-val="true" data-val-required="required text" type="radio" name="Choices" value="OptionOne" /></p>
<p><input type="radio" name="Choices" value="OptionTwo" /></p>

我希望两个单选按钮都能获得验证错误类,否则可能会导致用户选择的选项出现偏差。

我能做些什么?

4

3 回答 3

7

Please note that the expected behavior of the following code

@Html.RadioButtonFor(x => x.MyEnumProperty, MyEnum.OptionOne)
@Html.RadioButtonFor(x => x.MyEnumProperty, MyEnum.OptionTwo)
@Html.RadioButtonFor(x => x.MyEnumProperty, MyEnum.OptionThree)

is

<input id="MyEnumeration" type="radio" value="Option1" 
       name="MyEnumeration" 
       data-val-required="The MyEnumeration field is required." data-val="true">
<input id="MyEnumeration" type="radio" value="Option2" name="MyEnumeration">
<input id="MyEnumeration" type="radio" value="Option3" name="MyEnumeration">

Why? because Html.SomethingFor(model => model.Property) is meant to generate one html element for one particular property. The way you use it to create more than one element from one property is not correct.

Furthermore, look at the IDs of these 3 radio buttons. They are pretty the same, nah? Is it acceptable to have elements with the same IDs on a html page? Absolutely not! Therefore something needs to be fixed.

Although I thought solving this problem is easier by developing a new Html Extension Methods (reference 2), I tried to solve it in another way (because I'm so stubborn!).

First, We need to change the razor code:

<div>
    @Html.RadioButtonFor(m => m.MyEnumeration, MyEnum.Option1, new { id = "m1" })
    <label for="m1">
        OPTION 1</label>
    @Html.RadioButtonFor(m => m.MyEnumeration, MyEnum.Option2, new { id = "m2" })
    <label for="m2">
        OPTION 2</label>
    @Html.RadioButtonFor(m => m.MyEnumeration, MyEnum.Option3, new { id = "m3" })
    <label for="m3">
        OPTION 3</label>
</div>

Then, a piece of JavaScript/jQuery magic to fix our issue:

<script type="text/javascript">
    $(function () {
        $('[name=MyEnumeration]').each(function (index) { domAttrModified(this); });
    });

    function domAttrModified(obj) {
        //$obj = $(obj);
        $(obj).bind('DOMAttrModified', function () {
            if ($(obj).attr('class').indexOf('input-validation-error') != -1)
                $(obj).parent().addClass('input-validation-error');
            else
                $(obj).parent().removeClass('input-validation-error');
        });
    }
</script>

Anytime the first radio button raises a validation error, this JavaScript code applies error css class (input-validation-error) to the parent element of radio buttons, which is a <div> element.

And anytime validation error goes away (by clicking on any of the radio button elements), error style is removed from the parent element.

It works great in IE and FF, but unfortunately doesn't work in Chrome. The reason is Chrome doesn't support DOMAttrModified event. We can fix it by using this solution: https://stackoverflow.com/a/10466236/538387 , but maybe sometime later.

Again, I believe we need to develop an HTML Extension Method or improve and use an EditorTemplate like this: https://gist.github.com/973482

References:

  1. https://stackoverflow.com/a/7098541/538387
  2. https://stackoverflow.com/a/3448675/538387
  3. https://gist.github.com/973482
  4. Event detect when css property changed using Jquery
于 2012-06-29T21:38:13.303 回答
4

这可以通过使用showErrors回调来执行:

$("form").data("validator").settings.showErrors = function (errorMap, errorList) {
    this.defaultShowErrors();

    $("input[type=radio][data-val=true].input-validation-error").each(function () {
        $("input[name=" + $(this).attr('name') + "]").addClass("input-validation-error");
    });

    $("input[type=radio][data-val=true]:not(.input-validation-error)").each(function () {
        $("input[name=" + $(this).attr('name') + "]").removeClass("input-validation-error");
    });
};
于 2012-07-16T21:50:09.063 回答
-1

我所做的是禁用单选按钮的 CSS,只显示错误消息。(不确定 IE 是否喜欢这个)

.input-validation-error input[type="radio"]
{
    border: 0x solid #ff0000;
    background-color: inherit;
}
于 2011-08-10T18:35:28.460 回答