2

I'm using a template with custom CSS (.less) for checkboxes (making them appear as "Yes|No", "On|Off", etc.)

Using @Html.CheckboxFor(model => model.BooleanProperty, new { @class="custom-switch" }) results in a checkbox not appearing, at all.

So I got to digging around, found many questions on here with similar issues, but none of the solutions worked for me so far. The solution I'm currently working on is to use a custom EditorFor template. This is rendering the checkbox correctly, however, what I'm experiencing is that if the slider is switched to "NO", it's passing across to the controller as null instead of false, and if it's switched to "YES" it's passing across to the controller as "on".

I know that Html.CheckboxFor renders a checkbox element followed by a hidden input element. What purpose does this serve? Following are rendered HTML from the two methods as well any questions pertaining to that specific :

Straight HTML for Checkbox ::before ::after

When this is passed to the controller, why is the value of BoolProperty "true,false"?

@Html.CheckboxFor(model => model.BoolProperty, new { @class="custom-switch" })

<input checked="checked" data-val="true" data-val-required="The BoolProperty is required." id="BoolProperty" name="BoolProperty" type="checkbox" value="true" class="custom-switch">
<input name="BoolProperty" type="hidden" value="false">

What purpose does the hidden input field play? If I remember right, only the first "BoolProperty" named value would actually be passed to the controller anyways. I can't find anything that would suggest that one updates the other when the value changes, and through testing, I've noticed that the value does not change.

@Html.EditorFor(model => model.BoolProperty, new { @class = "custom-switch" })

<input type="checkbox" checked name="BoolProperty" class="custom-switch">
<label>::before ::after</label>

Why would this pass across the values of "on" or null to the controller? Why not true and false?

The Boolean Editor Template

@model Boolean?
var isChecked = ViewData["checked"] != null && ViewData["checked"].ToString() == "true";


<input type="checkbox" checked="@(isChecked ? "checked" : string.Empty)" name="@name"  class="@ViewData["class"].ToString()" />
<label class="lbl"></label>
Bardicer
  • 1,405
  • 4
  • 26
  • 43

2 Answers2

2

About the hidden field

I can't find anything that would suggest that one updates the other when the value changes, and through testing, I've noticed that the value does not change.

No, it doesn't change. The browsers, then a checkbox is not checked, don't submit anything using that name. So, the hidden propose is to submit the value "false" (with the same name) when the checkbox isn't checked.

When the checkbox is checked (as you said) the posted value is "true,false" (first the value of the checkbox and then the value of the hidden). The MVC binder deals with this string to convert it to true value setting it to the BooleanProperty.

About the on value

It is the default value for the checkbox. See here.

Community
  • 1
  • 1
Diego
  • 16,436
  • 26
  • 84
  • 136
2

The hidden field is there to force the field to be included in the form POST even when nothing is checked. Without it, the field is omitted altogether, per the standard. You wouldn't know the difference between a "false" value or a non-existent field.

http://www.w3.org/TR/html401/interact/forms.html

As far as why it uses "on" vs "true", that is something you can control yourself. If you want true/false instead of on/off, use that. "on" is just a default, but not required.

<input type="checkbox" class="checkbox" name="BoolProperty" value="true" />
<input type="hidden"   class="checkbox" name="BoolProperty" value="false" />
codenheim
  • 20,467
  • 1
  • 59
  • 80