Pass List of Checkboxes into View and Pull Out Ienumerable

Pass List of Checkboxes into View and Pull out IEnumerable

You cannot bind to a collection using a foreach loop. Nor should you be manually generating your html, which in this case would not work because unchecked checkboxes do not post back. Always use the strongly typed html helpers so you get correct 2-way model binding.

You have not indicated what you models are, but assuming you have a User and want to select Roles for that user, then create view models to represent what you want to display in the view

public class RoleVM
{
public int ID { get; set; }
public string Name { get; set; }
public bool IsSelected { get; set; }
}
public class UserVM
{
public UserVM()
{
Roles = new List<RoleVM>();
}
public int ID { get; set; }
public string Name { get; set; }
public List<RoleVM> Roles { get; set; }
}

In the GET method

public ActionResult Edit(int ID)
{
UserVM model = new UserVM();
// Get you User based on the ID and map properties to the view model
// including populating the Roles and setting their IsSelect property
// based on existing roles
return View(model);
}

View

@model UserVM
@using(Html.BeginForm())
{
@Html.HiddenFor(m => m.ID)
@Html.DisplayFor(m => m.Name)
for(int i = 0; i < Model.Roles.Count; i++)
{
@Html.HiddenFor(m => m.Roles[i].ID)
@Html.CheckBoxFor(m => m.Roles[i].IsSelected)
@Html.LabelFor(m => m.Roles[i].IsSelected, Model.Roles[i].Name)
}
<input type"submit" />
}

Then in the post method, your model will be bound and you can check which roles have been selected

[HttpPost]
public ActionResult Edit(UserVM model)
{
// Loop through model.Roles and check the IsSelected property
}

Use of IEnumerableT and foreach with hidden fields and checkbox not working to pass parameters from view to controller

Replace foreach by for loop

@for (int i = 0; i < Model.Count; i+=1)
{
.....
<input asp-for=@Model[i].IsAvailable type="checkbox" checked=@Model[i].IsAvailable />
....
@Html.DisplayFor(m => m[i].ProductName)
.... and so on
}

MVC Pass Selected Checkbox Items in Partial View to Controller

There are many ways to do this. One that requires the least changes to your code would be to:

  • Change your form to a Post and action to VerifyOrderInfo

    @using (Html.BeginForm("VerifyOrderInfo", "ReserveItem", FormMethod.Post))

  • Change IEnumerable to a List so you can bind by index

    public List<ItemProfileView> ItemProfile { get; set; }

  • Now you can reference the checkbox by index and add a hidden input for ItemId

    @Html.CheckBoxFor(r => r.ItemProfile[i].IsSelected, new { @class = "checkbox" })
    @Html.HiddenFor(r => r.ItemProfile[i].ItemId)

  • Use a submit button instead of an ActionLink

    <input type="submit" name="Verify Order Information" class="btn btn-primary btn-large" />

  • Add the model into the VerifyOrderInfo action so you can code against it

    public ActionResult VerifyOrderInfo(ItemDataView model)

Now when you submit the form it should send the model into the action with an ItemProfile list populated with ItemId and IsSelected form the input items.

Show list of checkboxes to create an object

Thanks to those links I could did it, this is my final HTTPost Method:

 [HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create( VMSalesman vmsalesman)
{
if (ModelState.IsValid)
{
List<Customer> list = new List<Customer>();
for (int i = 0; i < vmsalesman.CustomerList.Count; i++)
{
if (vmsalesman.CustomerList[i].IsSelected==true)
{
int n = vmsalesman.CustomerList[i].VMCustomerID;
list.Add(db.Customers.Where(c => c.CustomerID == n).First());
}
}
Salesman salesman = new Salesman() {
Name = vmsalesman.Name,
LastName = vmsalesman.LastName,
Location = vmsalesman.Location,
CustomersList = list
};
db.Salesmen.Add(salesman);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(vmsalesman);
}

Pass List of Checkboxes into View and Pull out IEnumerable

You cannot bind to a collection using a foreach loop. Nor should you be manually generating your html, which in this case would not work because unchecked checkboxes do not post back. Always use the strongly typed html helpers so you get correct 2-way model binding.

You have not indicated what you models are, but assuming you have a User and want to select Roles for that user, then create view models to represent what you want to display in the view

public class RoleVM
{
public int ID { get; set; }
public string Name { get; set; }
public bool IsSelected { get; set; }
}
public class UserVM
{
public UserVM()
{
Roles = new List<RoleVM>();
}
public int ID { get; set; }
public string Name { get; set; }
public List<RoleVM> Roles { get; set; }
}

In the GET method

public ActionResult Edit(int ID)
{
UserVM model = new UserVM();
// Get you User based on the ID and map properties to the view model
// including populating the Roles and setting their IsSelect property
// based on existing roles
return View(model);
}

View

@model UserVM
@using(Html.BeginForm())
{
@Html.HiddenFor(m => m.ID)
@Html.DisplayFor(m => m.Name)
for(int i = 0; i < Model.Roles.Count; i++)
{
@Html.HiddenFor(m => m.Roles[i].ID)
@Html.CheckBoxFor(m => m.Roles[i].IsSelected)
@Html.LabelFor(m => m.Roles[i].IsSelected, Model.Roles[i].Name)
}
<input type"submit" />
}

Then in the post method, your model will be bound and you can check which roles have been selected

[HttpPost]
public ActionResult Edit(UserVM model)
{
// Loop through model.Roles and check the IsSelected property
}

Checkboxlist MVC Partial

You use of name="@Html.IdFor(p => p.SelectedFruits)" generates name="CBL_SelectedFruits", but in order to bind to your model, you would need name="CBL.SelectedFruits" (note the . dot, not _ underscore) which you could generate using

name="@Html.NameFor(p => p.SelectedFruits)"

However there are other issues with your code. Your not strongly binding to your model, you get no validation, your generating a IList<SelectListItem> for property AvailableFruits when you don't need it (it could be just IList<string> AvailableFruits, and most importantly, if you return the view, all the checkboxes the user checked are lost (all checkboxes will be unchecked).

Change your view models so that you can strongly bind to your properties

public class FruitVM
{
public string Name { get; set; }
public bool IsSelected { get; set; }
}
public class ParentVM
{
public string TextField { get; set; }
public List<FruitVM> Fruits { get; set; }
}

and in the GET method

ParentVM model = new ParentVM
{
Fruits = new List<FruitVM>{
new FruitVM{ Name = "Apple" },
new FruitVM{ Name = "Pear" },
....
}
};
return View(model);

and create an EditorTemplate for FruitVM - in /Views/Shared/EditorTemplates/FruitVM.cshtml

@model FruitVM
@Html.CheckBoxFor(m => m.IsSelected)
@Html.LabelFor(m => m.IsSelected, Model.Name)

and in the view

@Html.ParentVM
....
@using (Html.BeginForm())
{
@Html.LabelFor(m => m.TextField)
@Html.EditorFor(m => m.TextField)

@Html.EditorFor(m => m.Fruits)

<input type="Submit" value="Save" />
}

The EditorFor() method will generate the correct html for each item in your collection.

Then in the POST method, you can get the selected items with

[HttpPost]
public ActionResult TestCheckboxlist(ParentVM model)
{
....
List<string> selectedFruits = model.Fruits.Where(x => x.IsSelected);

How to get list of checked boxes in controller

Your MVC controller should take FormCollection:

HttpPost, ValidateAntiForgeryToken]
public ActionResult Failid(FormCollection nv)

If nothing still comes back, verify the name is being rendered with your expectation. Also, I don't remember completely but do you have to set your own value with checkbox? In order to post something, a value must be specified, and this value is what gets sent back to the server, and then converted to a boolean by MVC.

How to bind post data from checkbox list back to custom class

With thanks to Stephen Muecke...

As described in the links suggested, it is possible to refer to the data model without using an instance of the data model. Therefore, this is the correct approach to render the checkboxes:

<div>
@for (int i = 0; i < Model.Modules.Count; i++)
{
@Html.CheckBoxFor(m => m.Modules[i].Checked)
@Html.LabelFor(m => m.Modules[i].Checked, Model.Modules[i].ModuleName)
<br />
}
</div>

This ensures that all the modules are listed, even if user doesn't actually select them all, and validation fails.

The model binding is then done automatically when the form is posted so the controller code for processing the form did not need amending need amending slightly. The code to get all the available modules should be static. That way all the modules can be "read"/made available conveniently. Then that static list is compared against the user-submitted list (which may only contains some or none of the available modules):

List<MyProductModule> allModules = ProductRequest.LoadModules();
foreach(MyProductModule sm in qd.Modules)
{
if(sm.Checked)
{
sb.AppendFormat("<li>{0}</li>", allModules[qd.Modules.IndexOf(sm)].ModuleName);
}
}


Related Topics



Leave a reply



Submit