12

I'm new from WebForms to MVC. I have view model field with the type bool? and, by default, EditorFor() renders this field as a DropDownList with a "Not Set" option. I would prefer to render it as a CheckBox and, if the value is null, just set it to unchecked.

The field name is RFP.DatesFlexible and so I wrote the following markup in my view:

<input type="checkbox" id="RFP_DatesFlexible" name="RFP.DatesFlexible" />
<label for="RFP_DatesFlexible">My Dates are Flexible</label>

But this doesn't work. The result is always null and ModelState.IsValid is false.

Can anyone say how I could make this work?

EDIT

This is the code I ended up with, which appears to work fine.

@Html.CheckBox("RFP.DatesFlexible", Model.RFP.DatesFlexible ?? false)
@Html.Label("RFP.DatesFlexible", "My Dates are Flexible")

The label is correctly associated with the checkbox so that clicking the text will toggle the checkbox.

1
  • Thank's for the answer! Commented Jun 1, 2015 at 9:08

3 Answers 3

5

Something like this?

Models:

public class MyViewModel
{
    public ViewModel2 RDP { get; set; }
}

public class ViewModel2
{
    public bool? DatesFlexible { get; set; }
}

Controller:

    public ActionResult TestBool()
    {
        return View(new MyViewModel { RDP = new ViewModel2() });
    }

    [HttpPost]
    public ActionResult TestBool(MyViewModel vm)
    {
        return View();
    }

View:

@model mvc_testing_2.Models.MyViewModel

@using (Html.BeginForm())
{
    @Html.CheckBox("RDP.DatesFlexible", 
        Model.RDP.DatesFlexible != null && (bool)Model.RDP.DatesFlexible)

    <input type="submit" value="go" />
}
Sign up to request clarification or add additional context in comments.

7 Comments

This won't work. The first argument is an error because it can't convert bool? to bool. And if I typecast it to a bool, I get an error because it's not a property.
Alright, then change it to this: @Html.CheckBox("DatesFlexible", Model.DatesFlexible != null && (bool)Model.DatesFlexible). This works, I just tested it. (Is RFP a property of another model? Model.RFP.DatesFlexible? If so, you'll probably need to name the input how you have it in your question, I can't remember off-hand)
That compiles--thanks. However, the field is still null when the page is submitted. Somehow, it's not picking up that the control is associated with the field. (The field is Model.RFP.DatesFlexible.)
Hmm, still seems to work fine for me when I rename the field to RFP.DatesFlexible (and change the Model.DatesFlexible to Model.RFP.DatesFlexible). Silly question: do you have the checkbox and submit button wrapped in a form?
Yes, I have a form and other values are set as expected. To clarify, you are saying it is posting back the values of the checkbox when you test? Is your field of type bool??
|
2

First, I think it would help to understand how Html.CheckBox works. It's not quite what you'd expect. Take a look at HTML.CheckBox Behaviour

To answer your question, the reason your code doesn't work is because your <input /> requires a value='true' to bind correctly. For example:

<input type='checkbox' name='RFP.DatesFlexible' value='true' />

And add a checked='checked' property if it should be checked.

That's why I usually override the Html.CheckBoxmethod with my own. The default implementation is just confusing.

2 Comments

Yes, that is confusing. I've edited my question to show the actual code I ended up using. I was still able to use the @Html syntax, as it offers some benefits. And, sure enough, if I examine the markup, it does contain the attribute value='true'.
@JonathanWood Your actual code above looks perfect, that's exactly what I would have done.
0

I know it's marked as accepted however I had the similar problem but I was iterating over sub items so I had problem with the name parameter bool? isOpen

When I used this is did bind to the ViewModel on post but rendered the dropdown:

@Html.EditorFor(model => model.Days[i].isOpen) 

This rendered the checkbox but values where null in the post:

@Html.EditorFor("isOpen", model.Days[i].isOpen ?? false) 

By looking at the rendered html I did this in the view which solved it:

@Html.CheckBox("Days[" + i +"].isOpen", Model.Days[i].isOpen ?? false)

I know it's know it's a bit quick n dirty but it worked

Hope this helps someone somewhere.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.