10

Sorry but most of my searches take me to old MVC codes. Any help will be appreciated.

In MVC 6 with tag helpers, how do you code a set of checkboxes:

  • Use tag helper for label so clicking it will toggle the checked value
  • Save (Bind?) the checked value to the IsOptionSelected property
  • Pass these checked values back to Controller after clicking Submit

?

I was able to display the checkboxes with labels correctly, but I do not know how to pass the checked values back to the controller via the model. Right now, IsOptionSelected values are coming back as false.

I was also able to make the html helper for the label work but not for the tag helper. I may be also coding these all wrong so any tips will help!

Here's what I have so far:

Display:

Phone Options Checkboxes

Entity:

public class PhoneOption
{
    public bool IsOptionSelected { get; set; } = false;
    public int OptionId { get; set; }
    public string OptionName { get; set; }
}

Model:

[Display(Name = "Phone Options")]
public IEnumerable<PhoneOption> PhoneOptions { get; set; }

. . . .
PhoneOptions = repository.GetPhoneOptions();

Repository:

public IEnumerable<PhoneOption> GetPhoneOptions()
{
    IEnumerable<PhoneOption> options = new[]
    {
        new PhoneOption { OptionId = 1, OptionName = "Phone Case",       IsOptionSelected = false },  
        new PhoneOption { OptionId = 2, OptionName = "Screen Protector", IsOptionSelected = false },
        new PhoneOption { OptionId = 3, OptionName = "Car Charger",      IsOptionSelected = false },
        new PhoneOption { OptionId = 4, OptionName = "Extra Cable",      IsOptionSelected = false }
    };
    return options;
 }

View:

<div class="form-group">
    <label class="control-label">Phone Options</label>
    <div>
        @foreach (var option in Model.PhoneOptions)
        {
            <div>
                @{ string cbId = "PhoneOption_" + @option.OptionId; }
                <input asp-for=@option.IsOptionSelected type="checkbox" value=@option.IsOptionSelected id=@cbId name=@cbId />
                @Html.Label(@cbId.ToString(), @option.OptionName)
                @*This is causing invalid operation exception*@
                @*<label asp-for=@cbId.ToString()>@option.OptionName</label>*@ 
                <span asp-validation-for=@cbId class="text-danger" role="alert"></span>
            </div>
        }
    </div>    
</div>

Thanks in advance!

ASh
  • 34,632
  • 9
  • 60
  • 82
niki b
  • 989
  • 3
  • 10
  • 30
  • I guess the asp-for is used in a wrong way. Change in the input the asp-for=@option.IsOptionSelected to asp-for="IsOptionSelected" that will make sure it is binded to the right property in PhoneOption. The same thing in the label asp-for=@cbId.ToString() is wrong.Check the tutorial here for tag helpers .http://www.davepaquette.com/archive/2015/05/18/mvc6-select-tag-helper.aspx – Helen Araya Apr 26 '16 at 14:50
  • Thanks for suggestion, but changing to asp-for="IsOptionSelected" is throwing a syntax error since it is not in the main model. It is part of the Model.PhoneOption option foreach iteration. asp-for=option.IsOptionSelected also will not work. And yes, I already read the tutorial before but it did not cover the checkbox list like what I am trying to do. – niki b Apr 26 '16 at 17:49
  • 1
    Ahh I got it. Check this if it helps http://stackoverflow.com/questions/15375800/model-binding-to-a-list-mvc-4 – Helen Araya Apr 26 '16 at 20:05
  • @AmeteGirl. +1 for the helpful link. – niki b Apr 26 '16 at 21:05

2 Answers2

11

This is finally what I did to make it to work. I am not sure if this is the best way to do it. I had to still use the html helpers because the tag helpers do not work.

Model:

public List<PhoneOption> PhoneOptions { get; set; }
. . .
PhoneOptions = repository.GetPhoneOptions().ToList();

View:

@if (@Model.PhoneOptions != null && @Model.PhoneOptions.Count() > 0)
{
    for (int i = 0; i < @Model.PhoneOptions.Count(); i++)
    {
        <div>
            <input asp-for="@Model.PhoneOptions[i].IsOptionSelected" type="checkbox" />
            <label asp-for="@Model.PhoneOptions[i].IsOptionSelected">@Model.PhoneOptions[i].OptionName</label>

            @*If these are not included, all OptionIds become 0 and all OptionName becomes null*@
            @Html.HiddenFor(x => @Model.PhoneOptions[i].OptionId)
            @Html.HiddenFor(y => @Model.PhoneOptions[i].OptionName)
        </div>
    }    
}

I hope this helps someone else who is having the same checkbox list issues.

UPDATE: I've updated the html helpers to tag helpers above.

niki b
  • 989
  • 3
  • 10
  • 30
  • 1
    Glad it worked for you.And thanks for posting your solution. – Helen Araya Apr 26 '16 at 22:09
  • 1
    Using tag helpers should work fine - `` so long as you use a `for` loop and the collection is `IList` (not `IEnumerable` –  Apr 26 '16 at 23:26
  • Thanks, @StephenMuecke! I tried it and it worked with a little change - ``. I still cannot make the tag helper for label to "attach" to the checkbox though. Both this: 1) `` and 2) `` are not clickable to toggle the checkbox value. If you know how, that will be great! – niki b Apr 27 '16 at 18:59
  • 1
    You need to remove the `id` attribute (the fact that its `id="@cbId"` suggests its not even unique and therefore your creating invalid html. - `` and `` –  Apr 27 '16 at 22:50
  • @StephenMuecke. That was actually the first thing I tried and initially it did not work. That is why I resorted to the manual id assignment (it is actually unique because it the OptionIds are unique) but not a very elegant solution I know. And now I changed it back to what you also suggested her and now it works! (scratching head). Must be something else I had that prevented the label from attaching to the checkbox. But thanks a lot! – niki b Apr 28 '16 at 02:08
1

This is how the syntax should be in your for each asp-for should be wrapped in a string with quotation marks

 @foreach (var option in Model.PhoneOptions)
        {
            <div>
                @{ string cbId = "PhoneOption_" + @option.OptionId; }
                <input asp-for="@option.IsOptionSelected" type="checkbox" value="@option.IsOptionSelected" id="@cbId" name="@cbId" />
                @Html.Label(@cbId.ToString(), @option.OptionName)
                @*This is causing invalid operation exception*@
                @*<label asp-for="@cbId">@option.OptionName</label>*@ 
                <span asp-validation-for="@cbId" class="text-danger" role="alert"></span>
            </div>
        }
Helen Araya
  • 1,886
  • 3
  • 28
  • 54
  • 1
    Sorry, I tried this but the IsOptionSelected values are still posting as false in the controller, even if the checkboxes are checked. – niki b Apr 26 '16 at 20:52