I Have a form in which I display a menu. Each menu has a section and choices as below:
Starters
Prawn Cocktail
Soup
Mains
Beef
Lamb
I am looping through the menu sections and menu choices for that section, for each menu option I want a radio button and to group them together per section so that only one menu option can be selected per section. By default the top selection will be selected. This is what I have so far
In the model
public List<MenuCourses> courses {get; set;}
public List<MenuOptions> options {get;set;}
and in the view
@for ( int i = 0; i < Model.MenuCourses.Count(); i++ ){
@Html.DisplayFor(m=> m.MenuCourses[i].CourseTitle )
// loop options
for ( int k = 0; k < Model.MenuOptions.Count(); k++ ){
if(Model.MenuOptions[k].MenuCoursesID == Model.MenuCourses[i].MenuCoursesID){
@Html.DisplayFor(m=> m.MenuOptions[k].Title)
//NEED RADIO BUTTON HERE BUT HOW DO I BIND TO THE MODEL?
}
}
I need each menu option to have a radio button grouped to that section, and when the user hits save I need to pick up which menu options has been selected.
Any help would be greatly appreciated
Thanks in advance
You can do this with EditorTemplates.
Let's create 3 view models for our scenario.
public class Course
{
public int ID { set; get; }
public string Name{ set; get; }
public List<Option> Options{ set; get; }
public int SelectedAnswer { set; get; }
public Course()
{
Options= new List<Option>();
}
}
public class Option
{
public int ID { set; get; }
public string Title { set; get; }
}
public class OrderViewModel
{
public List<Course> Courses{ set; get; }
public OrderViewModel()
{
Courses= new List<Course>();
}
}
In our GET
action method for the view, we will create an object of our OrderViewModel class and set the Course collection and it’s Options properties and then send that to the view by passing it to the View method.
public ActionResult Index()
{
var vm= new OrderViewModel();
//the below is hard coded for DEMO. you may get the data from some
//other place and set the course and options
var q1 = new Course { ID = 1, Name= "Starters" };
q1.Options.Add(new Option{ ID = 12, Title = "Prawn Cocktail " });
q1.Options.Add(new Option{ ID = 13, Title = "Soup" });
vm.Courses.Add(q1);
var q2 = new Course { ID = 1, Name= "Mains" };
q2.Options.Add(new Option{ ID = 42, Title = "Beef" });
q2.Options.Add(new Option{ ID = 43, Title = "Lamp" });
vm.Courses.Add(q2);
return View(vm);
}
Now go to the ~/Views/YourControllerName
folder and create a folder called EditorTemplates
. Create a new view there with the name Course.cshtml
. Add the below code to that file
@model Course
<div>
@Html.HiddenFor(x=>x.ID)
<h3> @Model.Name</h3>
@foreach (var a in Model.Options)
{
<p>
@Html.RadioButtonFor(b=>b.SelectedAnswer,a.ID) @a.Title
</p>
}
</div>
Now go to the main view and use EditorFor
html helper method to bring the editortemplate
@model OrderViewModel
<h2>Your Order</h2>
@using (Html.BeginForm())
{
@Html.EditorFor(x=>x.Courses)
<input type="submit" />
}
To get the selected items on form submit, you can do this
[HttpPost]
public ActionResult Index(OrderViewModel model)
{
if (ModelState.IsValid)
{
foreach (var q in model.Courses)
{
var qId = q.ID;
var selectedAnswer = q.SelectedAnswer;
// Save the data
}
return RedirectToAction("ThankYou"); //PRG Pattern
}
//to do : reload courses and options on model.
return View(model);
}
This is clearly explained in this blog post with a working sample which you can download and run yourself and see how it works.