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.

Jonathan Wood
  • 65,341
  • 71
  • 269
  • 466

3 Answers3

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" />
}
hawkke
  • 4,242
  • 1
  • 27
  • 23
  • 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. – Jonathan Wood Dec 13 '11 at 04:12
  • 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) – hawkke Dec 13 '11 at 04:19
  • 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.) – Jonathan Wood Dec 13 '11 at 04:24
  • 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? – hawkke Dec 13 '11 at 04:31
  • 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?`? – Jonathan Wood Dec 13 '11 at 04:33
  • Yep, no problems. I edited my answer so you can see all my code. Heading to bed now, so good luck. I'll check on you tomorrow :) – hawkke Dec 13 '11 at 04:39
  • D'oh! Right you are. I had forgot to add "RFP." to the beginning of the first string argument. That did correct it. Many thanks! – Jonathan Wood Dec 13 '11 at 04:44
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.

Community
  • 1
  • 1
Scott Rippey
  • 15,614
  • 5
  • 70
  • 85
  • 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'`. – Jonathan Wood Dec 13 '11 at 15:14
  • @JonathanWood Your actual code above looks perfect, that's exactly what I would have done. – Scott Rippey Dec 13 '11 at 20:08
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.

scott_lotus
  • 3,171
  • 22
  • 51
  • 69
Tomas Hesse
  • 385
  • 3
  • 10