How to implement checkbox list in ASP.NET Core?

I am trying to implement a checklist in ASP.NET Core, but have encountered some difficulties.

My ViewModel:

public class GroupIndexViewModel { public Filter[] Filters { get; set; } } public class Filter { public int Id { get; set; } public string Name { get; set; } public bool Selected { get; set; } } 

My view:

 @model GroupIndexViewModel <form asp-action="Index" asp-controller="Group" method="get"> <ul> @for (var i = 0; i < Model.Filters.Length; i++) { <li> <input type="checkbox" id="@Model.Filters[i].Name" asp-for="@Model.Filters[i].Selected" value="@Model.Filters[i].Selected" checked="@Model.Filters[i].Selected" /> <label for="@Model.Filters[i].Name">@Model.Filters[i].Name</label> </li> } </ul> <button type="submit" name="action">Filtrer</button> </form> 

When publishing in my controller, the Filter property in my viewmodel shows highlighted false, even if it is selected in the view.

+29
c # asp.net-mvc asp.net-core
source share
4 answers

I would take the next path.

 @model GroupIndexViewModel <form asp-action="Index" asp-controller="Group" method="get"> <ul> @for (var i = 0; i < Model.Filters.Count; i++) { <li> <input type="checkbox" asp-for="@Model.Filters[i].Selected" /> <label asp-for="@Model.Filters[i].Selected">@Model.Filters[i].Name</label> <input type="hidden" asp-for="@Model.Filters[i].Id" /> <input type="hidden" asp-for="@Model.Filters[i].Name" /> </li> } </ul> <button type="submit" name="action">Filtrer</button> </form> 

Here, I assume that you have the correct controller and action implementation.

+36
source share

This question could already be answered, but I wanted to explain your problem so that others could understand what was happening.

You do not know that you have already set the value false to your input, since you are using attributes incorrectly.

Let's look at your view

 @model GroupIndexViewModel <form asp-action="Index" asp-controller="Group" method="get"> <ul> @for (var i = 0; i < Model.Filters.Length; i++) { <li> <input type="checkbox" id="@Model.Filters[i].Name" asp-for="@Model.Filters[i].Selected" value="@Model.Filters[i].Selected" checked="@Model.Filters[i].Selected" /> <label for="@Model.Filters[i].Name">@Model.Filters[i].Name</label> </li> } </ul> <button type="submit" name="action">Filtrer</button> </form> 

So first. You create input elements from the Filter array. Now let's take a closer look at your input element.

 <input type="checkbox" id="@Model.Filters[i].Name" asp-for="@Model.Filters[i].Selected" value="@Model.Filters[i].Selected" checked="@Model.Filters[i].Selected" /> 

Now let me explain this.

  1. You specify the type using the type attribute.
  2. You specify the identifier using the id attribute.
  3. You bind input to the model using the asp-for tag helper.
  4. You specify the value to enter using the value attribute.
  5. Finally, you set the input as marked using the checked attribute.

If you look at the Tag Helper Documentation , you will find the connection between the .Net Type and Input Type , realizing that:

The flags contain a logical value corresponding to the model and formatted by the tag helper as type="checkbox" .

Since you use the type="checkbox" attribute, the Tag Helper value can only be true or false . So, if we go back and look at the input element, you are already specifying a value for the input. Although the tag assistant can assign a value to the input, it cannot override what is already specified. Therefore, your input will always have the value you specify, in this case boolean is always false by default.

Now you might think that your input element is false , and for example, adding checked="checked" will not change the value to true , since the value attributes override the checked attribute. Causes poor implementation of both attributes.

Therefore, you should use only one attribute. (Either value or checked ). You can use them for convenience. But in this case, you should use the default attribute checked . Since you are implementing a Tag Helper and an input value, they must be of type boolean . And the value of the checked attribute returns a boolean and, for example, this is the value used by the tag assistant.

Thus, the implementation provided by @dotnetstep should work, as it only declares an auxiliary tag in the input element. Thus, Tag Helper processes the corresponding input attributes.

 @model GroupIndexViewModel <form asp-action="Index" asp-controller="Group" method="get"> <ul> @for (var i = 0; i < Model.Filters.Count; i++) { <li> <input type="checkbox" asp-for="@Model.Filters[i].Selected" /> <label asp-for="@Model.Filters[i].Selected">@Model.Filters[i].Name</label> <input type="hidden" asp-for="@Model.Filters[i].Id" /> <input type="hidden" asp-for="@Model.Filters[i].Name" /> </li> } </ul> <button type="submit" name="action">Filtrer</button> </form> 
+15
source share

Based on @dotnetstep's answer, I created a tag helper that takes an IEnumerable model from SelectListItem and generates the fields described in its answer.

Here is the tag helper code:

 [HtmlTargetElement(Attributes = "asp-checklistbox, asp-modelname")] public class CheckListBoxTagHelper : TagHelper { [HtmlAttributeName("asp-checklistbox")] public IEnumerable<SelectListItem> Items { get; set; } [HtmlAttributeName("asp-modelname")] public string ModelName { get; set; } public override void Process(TagHelperContext context, TagHelperOutput output) { var i = 0; foreach (var item in Items) { var selected = item.Selected ? @"checked=""checked""" : ""; var disabled = item.Disabled ? @"disabled=""disabled""" : ""; var html = $@ "<label><input type=""checkbox"" {selected} {disabled} id=""{ModelName}_{i}__Selected"" name=""{ModelName}[{i}].Selected"" value=""true"" /> {item.Text}</label>"; html += $@ "<input type=""hidden"" id=""{ModelName}_{i}__Value"" name=""{ModelName}[{i}].Value"" value=""{item.Value}"">"; html += $@ "<input type=""hidden"" id=""{ModelName}_{i}__Text"" name=""{ModelName}[{i}].Text"" value=""{item.Text}"">"; output.Content.AppendHtml(html); i++; } output.Attributes.SetAttribute("class", "th-chklstbx"); } } 

You need to add the following to the _ViewImports.cshtml file:

 @addTagHelper *, <ProjectName> 

Then, to lower the checklist window into a razor, view it as easily as:

 <div asp-checklistbox="Model.Brands" asp-modelname="Brands"></div> 

You may notice that I am adding a class attribute to the div to style the field and its contents. Here is the CSS:

 .th-chklstbx { border: 1px solid #ccc; padding: 10px 15px; -webkit-border-radius: 5px ; -moz-border-radius: 5px ; -ms-border-radius: 5px ; border-radius: 5px ; } .th-chklstbx label { display: block; margin-bottom: 10px; } 
+6
source share

I just tried this and it worked:

 <input asp-for="filter.type[i].IsEnabled"/> 

without a flag, and then the corresponding logical value in the model with a hidden identifier and name.

0
source share

All Articles