1

I'm currently working on an ASP.NET Core 3.1 MVC application. I need to create a dynamic checkbox menu, which shows available fruits and stores the selected fruits into another data source.

My problem is, I cannot check/click any checkbox on my view and send the selected items back to my controller.

My FruitsViewModel looks like this:

public class FruitsViewModel
{
    public IList<string> SelectedFruits { get; set; } = new List<string>();

    public IList<SelectListItem> AvailableFruits { get; set; } = new List<SelectListItem>();
}

My FruitsController looks like this:

public class FruitsController : Controller
{
    [HttpGet]
    public async Task<IActionResult> Index()
    {
        var viewModel = new FruitsViewModel { 
                                                  AvailableFruits = GetAvailableFruits()
                                                };

        return View(viewModel);
    }

    [HttpPost]
    public async Task<IActionResult> Index(FruitsViewModel fruitsViewModel)
    {
        // ... process data
    }

    private IList<SelectListItem> GetAvailableFruits()
    {   
        // the values are originally retrieved from a DB, here I use just sample data   
        return new List<SelectListItem>
                       {
                           new SelectListItem {Text = "Apple", Value = "Apple"},
                           new SelectListItem {Text = "Pear", Value = "Pear"},
                           new SelectListItem {Text = "Banana", Value = "Banana"},
                           new SelectListItem {Text = "Orange", Value = "Orange"},
                       };
    }
}

My FruitsController Index.cshtml view looks like this:

<form method="post">
    <div class="form-group row">
        <!-- Fruits -->
        <label class="col-4">Fruits</label>
        <div class="col-8">
            @foreach (SelectListItem availableFruit in Model.AvailableFruits)
            {
                <div class="custom-control custom-checkbox custom-control-inline">
                    <label class="custom-control-label">
                        <input type="checkbox"
                               class="custom-control-input"
                               name="SelectedFruits"
                               value="@availableFruit.Value"
                               @if (Model.SelectedFruits.Contains(availableFruit.Value))
                               {
                                   @:checked
                               }/>
                        @availableFruit.Text
                    </label>
                </div>
            }
        </div>
    </div>
    <div class="form-group row">
        <div class="offset-4 col-8">
            <button name="submit" type="submit" class="btn btn-info">Send</button>
        </div>
    </div>
</form>

Do you know how to check a checkbox which is loaded dynamically on a ASP.NET Core MVC view and send the selected value back to the controller accordingly?

If possible I don't want to use jQuery.

I already followed this similar post.

azzurro123
  • 521
  • 2
  • 10
  • 19
  • It makes sense. The values in your model are hardcoded in get method and every time form is submitted you redirect to Index by get. As a consequence whatever you changed is reset to its original value. – derloopkat Sep 11 '20 at 09:43
  • thanks for your comment. I changed my demo accordingly - the hard coded data is for the sample only. :) – azzurro123 Sep 11 '20 at 09:49
  • I still cannot click any checkbox on my view – azzurro123 Sep 11 '20 at 09:56
  • With the above code, instead of redirecting to index, you just do `fruitsViewModel.AvailableFruits = GetAvailableFruits(); return View(fruitsViewModel);`. That way selected options are preserved. – derloopkat Sep 11 '20 at 10:17

1 Answers1

0

I cannot check/click any checkbox on my view and send the selected items back to my controller.

You can try to modify the code like below to dynamically generate checkbox(es) with Bootstrap styles.

<div class="col-8">
    @foreach (SelectListItem availableFruit in Model.AvailableFruits)
    {
        <div class="custom-control custom-checkbox custom-control-inline">
            <input type="checkbox" id="@availableFruit.Value"
                    class="custom-control-input"
                    name="SelectedFruits"
                    value="@availableFruit.Value"
                    @if (Model.SelectedFruits.Contains(availableFruit.Value)) { @: checked
                    } />
            <label class="custom-control-label" for="@availableFruit.Value">@availableFruit.Text</label>
        </div>
                
    }
</div>

Test Result

Checked options

enter image description here

Get checked values in action method

enter image description here

Fei Han
  • 26,415
  • 1
  • 30
  • 41
  • Thanks Fei Han. Ineed it works like a charm. It wouldn't work without the id though, it seems i forgot this guy. have a nice day. – azzurro123 Sep 11 '20 at 10:10
  • 1
    `It wouldn't work without the id though` Yes, **id** attribute of input field and **for** attribute of label should be matched. Glad to hear the problem is solved. – Fei Han Sep 11 '20 at 10:13