mvc bind/post boolean to radiobutton
Asked Answered
B

4

13

I have a column in my Model with a NULLABLE boolean value. Now on my View (for editing), I would like to bind that to two radiobuttons: Yes & No. If the value is null, then just have the two radiobutton un-checked. How would I go to do that?

Thanks.

Bontebok answered 6/5, 2010 at 19:48 Comment(0)
L
24

Once you have selected a radio button, there's really no way to unselect it (as a user). I'd suggest that if you really need a three-valued result, that you have three radio buttons -- Yes, No, Don't care.

<%= Html.LabelFor( m => m.Foo ) %>
<%= Html.RadioButtonFor( m => m.Foo, "true" ) %> Yes
<%= Html.RadioButtonFor( m => m.Foo, "false" ) %> No
<%= Html.RadioButtonFor( m => m.Foo, string.Empty ) %> Don't Care
<%= Html.ValidationMessageFor( m => m.Foo ) %>
Lothians answered 6/5, 2010 at 19:54 Comment(6)
Thanks :) Forgot about my question until today, Html.RadioButtonFor solved the problem.Bontebok
I came up with the same solution, but somehow if Foo is null the Don't care radio is not checked...Any ideas why?Menswear
@MichalB. I'm not sure. It uses Convert.ToString() on the model property (and on the value as well). If the bool? is null that should convert to string.Empty and the button should be checked.Lothians
Yeap. it's not. I have a condition that checks if the value is null and in such case applies html attribute checked="checked" to the last radio button. It doesn't work otherwise...Menswear
Although this will allow selection of a new value, RadioButtonFor() will not select current values from the bound variable. It needs to set the checked attribute conditionally. Because of this it should not be the accepted answer. Sorry.Reify
This solution is exactly what I needed! string.Empty is THE way to pass a null value to the controller. I used @string.Empty for those using Razor btwIthaca
S
4

I can across this post late, however here is my solution which handles the setting the values as well. This used an Editor template. You will need to specify the Editor template name. I called mine 'NullableBool'

@model bool?

@{

Layout = null;

IDictionary<string, object> yesAttributes = new Dictionary<string, object>();
IDictionary<string, object> noAttributes = new Dictionary<string, object>();
IDictionary<string, object> naAttributes = new Dictionary<string, object>();

if (Model.HasValue)
{
    if (Model.Value)
    {
        yesAttributes.Add("checked", "checked");
    }
    else
    {
        noAttributes.Add("checked", "checked");
    }
}
else
{
    naAttributes.Add("checked", "checked");
}
}

@Html.RadioButtonFor(m => m, "true", yesAttributes) Yes`

@Html.RadioButtonFor(m => m, "false", noAttributes) No`

@Html.RadioButtonFor(m => m, string.Empty, naAttributes) N/A`
Sincerity answered 31/1, 2014 at 19:59 Comment(0)
R
3

The use of multiple Html.RadioButtonFor (m => m.Foo, "true") seems to generate invalid HTML, because it generates controls with identical IDs:

<input **id="Foo"** ... type="radio" value="True">
<input **id="Foo"** ... type="radio" value="False">

I have solved this by making the radio buttons directly in html:

<input type="radio" name="Foo" value="true" id="Foo_True"
       <%:Html.WriteCheckedIfTrue(Model.Foo.HasValue && Model.Foo.Value)%>/>
       <label for="Foo_True">Yes</label><br/>

<input type="radio" name="Foo" value="false" id="Foo_False" 
       <%:Html.WriteCheckedIfTrue(Model.Foo.HasValue && !Model.Foo.Value)%>/> 
       <label for="Foo_False">No</label><br/>

<input type="radio" name="Foo" value="" id="Foo_Null" 
       <%:Html.WriteCheckedIfTrue(!Model.Foo.HasValue)%>/> 
       <label for="Foo_Null">Don't Care</label>

make sure to name the radio buttons according to the used viewmodel, eg: Model.Filter.HasImage is named: Filter.HasImage to work with model binding

The "html helper" looks like this:

    public static MvcHtmlString WriteCheckedIfTrue(this HtmlHelper htmlHelper, 
                                                   bool validation)
    {
        if(validation)
            return new MvcHtmlString("checked=\"checked\"");

        return new MvcHtmlString(string.Empty);
    }
Reportorial answered 20/8, 2012 at 21:2 Comment(1)
Note that you can just override the ID that the helpers generate.Varletry
S
1

This is a razor solution to the problem. This is a very old ASP question.

The problem is that you need to set the checked attribute because the Html.RadioButtonFor does not check a radio button based on a nullable bool (which appears to be a flaw).

Also by putting the radio buttons inside of the label tag, you can select value by clicking the label.

Shared/EditorTemplates/Boolean.cshtml

@model bool?
<label>
    <span>n/a</span>
    @Html.RadioButtonFor(x => x, "", !Model.HasValue ? new { @checked=true } : null) 
</label>
<label>
    <span>Yes</span>
    @Html.RadioButtonFor(x => x, true, Model.GetValueOrDefault() ? new { @checked = true } : null)
</label>
<label>
    <span>No</span>
    @Html.RadioButtonFor(x => x, false, Model.HasValue && !Model.Value ? new { @checked = true } : null)
</label>
Strachan answered 16/9, 2015 at 14:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.