Checkbox not working with boolean viewmodel property - c#

I am using MVC6 and have a checkbox input field in my form, but when the form is submitted the value for the checkbox always gets passed to the ViewModel as false:
Here is how the property is declared in my ViewModel:
[Display(Name = "Include Sales Tax")]
public bool IncludeSalesTax { get; set; }
Here is how the form looks in my MVC6 razor form:
<div class="form-group">
<div class="checkbox">
<label><input asp-for="IncludeSalesTax" type="checkbox" value="">#Html.DisplayNameFor(m => m.IncludeSalesTax)</label>
</div>
</div>
I figured the above would be the best way to follow Twitter Bootstrap standards and use the ASP.NET MVC6 asp-for tag for model binding.
When I submit the form the value for IncludeSalesTax is always false, even when checked. What am I doing wrong?

input type checkbox sends an "on" if it is set. Otherwise it is not sent.
It is important, that you set the value attribute to true. In this case it sends true or nothing, which is perfect to bind to a boolean.
<input type="checkbox" name="yourPropertyName" value="true" checked />

Pinki's answer above is good if the checkbox should default to checked.
If the checkbox should default to unchecked, a little in-line javascript sets the value to true or false upon clicking:
<input name="yourPropertyName" type="checkbox" value="false" onchange="this.value=this.checked">

After letting Visual Studio generate the form based on my ViewModel here is how it does it:
<div class="checkbox">
<input asp-for="isTaxable" />
<label asp-for="isTaxable"></label>
</div>
Additionally, I was missing the closing of my input tag. So it can also be done like this which is the bootstrap preferred way:
<label><input asp-for="isTaxable" type="checkbox" value=""/>#Html.DisplayNameFor(m => m.isTaxable)</label>

The razor view engine normally creates a checkbox and one hidden input using the same name.
You can simply use the html below to ensure you get your desired result:
<div class="form-group">
<div class="checkbox">
<input type="checkbox" value="true" name="IncludeSalesTax" />Include Sales Tax
<input type="hidden" value="false" name="IncludeSalesTax" />
</div>
</div>

Related

How to properly display checkbox form controls in ASP.NET Core Views?

I have a model with a boolean property which will be shown as a checkbox in my view:
public class SomeModel
{
public bool SomeProperty { get; set; }
}
And I am creating the view like this:
<div class="form-check">
<input asp-for="TestProperty" value="true" class="form-check-input" />
<label class="form-check-label" asp-for="TestProperty"></label>
</div>
Below is the HTML output in the browser:
<div class="form-check">
<input value="true" class="form-check-input" type="checkbox" data-val="true" data-val-required="The TestProperty field is required." id="TestProperty" name="TestProperty">
<label class="form-check-label" for="TestProperty">TestProperty</label>
</div>
And I can see below hidden element is appended at the end of the form:
<input name="TestProperty" type="hidden" value="false">
When I submit the form this is the request body:
TestProperty: true
TestProperty: false
The value in the first line is the value in the check box element and the second line is the value of the hidden element that overrides the first line value when received in the controller. I noticed that when I click on the checkbox the hidden input's value does not change.
The first solution that comes to mind is to update the hidden element via JavaScript when the input's value is changed, which this is unnecessary. Is there any way that I can get rid of these hidden elements? or I am not displaying the form control properly. I am not sure.
UPDATE
The hidden input elements are added automatically by the razor view itself. Though I am using controllers/views and not razor views, I tested Enrico's solution and the result is the same. It still appends a hidden input element for the checkbox:
You don't need to manually add an hidden input field, or to interact with it via client side Javascript code. The way to go with ASP.NET core and Razor is using the tag helpers and let the actual HTML generation to be done by Razor itself.
This is an example using Razor Pages and a single boolen value in the page input model. I have used ASP.NET core 3.1 and the usual ASP.NET core web application template in Visual Studio 2019.
This is the page model:
public class TestFormModel : PageModel
{
private readonly ILogger _logger;
public TestFormModel(ILogger<TestFormModel> logger)
{
_logger = logger;
}
[BindProperty]
public InputModel Input { get; set; }
public IActionResult OnGet()
{
this.Input = new TestFormModel.InputModel
{
ShowUsername = false
};
return this.Page();
}
public IActionResult OnPost()
{
if (!this.ModelState.IsValid)
{
return this.Page();
}
_logger.LogInformation("The posted value is: {Value}", this.Input.ShowUsername);
return this.RedirectToPage("Index");
}
public class InputModel
{
[Display(Name = "Show User Name")]
public bool ShowUsername { get; set; }
}
}
This is the associated Razor view:
#page
#model StackoverflowTest.Pages.TestFormModel
#{
ViewData["Title"] = "How to build a form with a checkbox";
}
<h1>#ViewData["Title"]</h1>
<form asp-page="TestForm">
<div class="form-check">
<input class="form-check-input" asp-for="Input.ShowUsername">
<label class="form-check-label" asp-for="Input.ShowUsername"></label>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
That's it. You do not need to manually add an hidden input in your form. You just have to use the proper tag helps and ASP.NET core will take care of generating the right form and form inputs for you.
UPDATE 2 August 2021
See this github repository for a working sample.
As a sidenote, please consider that the hidden input field is automatically added by ASP.NET core and it is required in order to post to the server the right value for Input.ShowUsername when the checkbox in the form is unchecked.
Basically in the generated HTML page source there are two form inputs for Input.ShowUsername. One of them is an HTML input having type="checkbox", the other one is an HTML input having type="hidden". Both of them have the same value for the name attribute (name="Input.ShowUsername"), while the value attribute is true for the checkbox input and false for the hidden input.
This is the HTML page source for the form (exactly the way it is generated by ASP.NET core 3.1):
<form action="/TestForm" method="post">
<div class="form-check">
<input class="form-check-input" type="checkbox" data-val="true" data-val-required="The Show User Name field is required." id="Input_ShowUsername" name="Input.ShowUsername" value="true">
<label class="form-check-label" for="Input_ShowUsername">Show User Name</label>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8AHG4SVs1BBFruMHNiza3QNKvHNf96d_oiz5J6n3eYuncnlFKqvL4x3G6jbAOmNfJjrwk_crqFN99kjZiBVoboFGd0VQIBlrvmp9fL6p8CMbiZ4f6Cf4rm3OpGZEZ_04UQQ5iuUi3nVjfIgfb5-vctw" />
<input name="Input.ShowUsername" type="hidden" value="false">
</form>
When the checkbox in the form is checked, the value true is posted to the server for the name Input.ShowUsername, when the checkbox is unchecked the value false is posted to the server for the name Input.ShowUsername: this works because the value of unchecked checkboxes is not posted to the server.
Adding an input with type="hidden" is a common pattern to post a default value for the checkbox when it is unchecked, see here for an explanation about the way HTML checkboxes work.
Again, all of this is automatically generated for you by ASP.NET core: you simply have to define the page input model and to use the proper Razor tag helpers.

Bind radiobuttons to two different fields with Angular

need some help on radio buttons. How can i bind 2 radio buttons that are for one particular question but use 2 different fields in the database. For example there is a question that has a Yes/No answer. The yes answer binds to one field, and the No answer to another, they don't bind to a single filed that has a true, false value.
<div class="radio-s">
<input type="radio" ng-value="true" data-name="use_plan"
data-value="true" ng-model="record.offer_plan" />
<label>Yes</label>
</div>
<div class="radio-s">
<input type="radio" ng-value="false" data-name="use_plan"
data-value="true" ng-model="record.offer_plan" />
<label>No</label>
</div>
Thanks in advance.
Attach the name attribute to both of your radio buttons so that only one can be selected at a time and also bind them to the respective fields from your DB
<div class="radio-s">
<input type="radio" name="planGroup" ng-value="true" data-name="use_plan"
data-value="true" ng-model="record.offer_plan_yes" />
<label>Yes</label>
</div>
<div class="radio-s">
<input type="radio" name="planGroup" ng-value="false" data-name="use_plan"
data-value="true" ng-model="record.offer_plan_no" />
<label>No</label>
</div>

How to avoid #Html.CheckBoxFor generating hidden field?

Using #Html.CheckBoxFor generates a hidden field. Is there a way I can avoid generating that ?
Why I want to do that ? I was provided design, which has some script or library used in it for visual display. It works fine if Html is in below format (Checkbox with Label):
<div>
<input type="checkbox" value="resources" id="resources" class="cb">
<label for="resources">
I need an offset facility
</label>
<i class="tooltip-icon" data-icon="repayments"></i>
</div>
But it do not work if there is a hidden field between Checkbox and Label:
<div>
<input id="HomeLoanLead_Redraw_flexibility_Value" class="cb" type="checkbox" value="true" name="HomeLoanLead.Redraw_flexibility_Value" data-val-required="The Redraw_flexibility_Value field is required." data-val="true">
<input type="hidden" value="false" name="HomeLoanLead.Redraw_flexibility_Value">
<label for="HomeLoanLead_Redraw_flexibility_Value"> I want to make extra repayments </label>
<i class="tooltip-icon" data-icon="loan"></i>
</div>
If I try using <input type=checkbox> I m afraid I will not get out of box model binding in post action.
Please help.

HttpContext.Current.Request.Form checkbox

I am posting my form to an MVC Controller, where I want to process some changes the user has made on a grid like html structure.
I have checkboxes rendered as simple HTML in my View for each row :
<input type="checkbox" id="cbxR1" checked="checked" />
<input type="checkbox" id="cbxR2" checked="checked" />
I would like to know how I would retrieve a checkbox value after an AJAX post.
I am trying to use the following to retrieve the
HttpContext.Current.Request.Form["cbxR1"]
and am always getting a null, regardless of whether the checkbox was checked or not.
The cbxR1, cbxR2 should be the name of an input element, not the id.
<form ...>
<input type="checkbox" name="cbxR1" checked="checked" />
<input type="checkbox" name="cbxR2" checked="checked" />
</form>

Set Label for checkbox in razor

How does one set the label of a checkbox? I looked at some sites and they are using lambda expressions, but I can't understand them. I am new to asp.net MVC.
#{
bool chkVal = false;
}
<li>#Html.CheckBox("chksumma",chkVal,new {#value = "5"})</li>
<li>#Html.LabelFor(, "");
This is a really good way:
<div class="checkbox">
<label>#Html.CheckBoxFor(x => item.IsSelected) #Html.DisplayNameFor(x => item.IsSelected)</label>
</div>
It's what is recommended by bootstrap 3.
It works in a table.
You can click on the check box OR the label to select the box. (This is an important usability feature.)
The cursor is properly the "hand" instead of the arrow pointer.
EDIT
This is really easy to do in Bootstrap 4.
You just wrap your label and input inside form-check markup:
<div class="form-check">
<input class="form-check-input" type="checkbox" value="" id="defaultCheck1">
<label class="form-check-label" for="defaultCheck1">Default checkbox</label>
</div>
If you are using a Model you could do:
<li>#Html.CheckBoxFor(f=> f.chksumma)</li>
<li>#Html.LabelFor(f=> f.chksumma)</li>
Then use the attributes TGH pointed out
otherwise if you don't have a model all you can do for labels is:
#Html.Label("LabelText")
which prints a standalone label
or and craft it if you want it to link with the item
<label for="chksumma">LAbelText</label>
If you really don't want to hand craft it you can write your own HTML helper as explained here
http://develoq.net/2011/how-to-create-custom-html-helpers-for-asp-net-mvc-3-and-razor-view-engine/
I'm assuming that you want the label to tick the checkbox when you click on it.
In this case, the for attribute of the HTML <label> field must point to the ID of the relevant input element.
If you're using a model, #Html.CheckBoxFor will generate a checkbox without an ID, so you will need to add an ID to the checkbox, then point your label to the same ID. The easiest way is to replicate the checkbox's name into its ID field using the #Html.NameFor helper method. Here's an example:
#Html.CheckBoxFor(x => x.Active, new {id=Html.NameFor(x => x.Active)})
<label for="#Html.NameFor(x => x.Active)">Active</label>
Generated HTML (without validation attributes):
<input id="[0].Active" name="[0].Active" type="checkbox" value="true" />
<input name="[0].Active" type="hidden" value="false" />
<label for="[0].Active">Active</label>
I worked on something similar and got around it by this snipped code
<div class="row">
<div class="col-xs-3">
<label>
#Html.CheckBoxFor(x => x.AdvanceSearch.IsExactPhrase)
#Html.LabelFor(x => x.AdvanceSearch.IsExactPhrase)
</label>
</div> ...
Hope it helps the others
You shouldn't need the <label> tag at all:
<div class="block mTop20">
#HtmlCheckboxFor(f => f.prop)
#Html.LabelFor(f=>f.prop,"This is the label text")
</div>

Categories