Reputation: 1226
I have nested foreach loops in my view, and am having problems with the radio buttons.
@foreach (var header in Model.surveyHeaders)
{
<h1>@header.Name</h1>
foreach (var subHeader in Model.surveySubHeaders.Where(x => x.SurveryHeaderID == header.ID))
{
<h2>@subHeader.Name</h2>
foreach (var question in Model.surveyQuestions.Where(x => x.SurveySubHeaderID == subHeader.ID))
{
@Html.RadioButtonFor(x => x.surveyResults.Where(y => y.SurveyQuestionID == question.ID).First().Value, 1);
@Html.RadioButtonFor(x => x.surveyResults.Where(y => y.SurveyQuestionID == question.ID).First().Value, 2);
@Html.RadioButtonFor(x => x.surveyResults.Where(y => y.SurveyQuestionID == question.ID).First().Value, 3);
@question.Question
}
}
}
The radio button name is always 'Value', so the radio buttons are not grouped. What can I do to achieve the grouping that is desired?
Upvotes: 1
Views: 866
Reputation: 56429
Ah collections in MVC, the joy! In order to make sure all fields are named accordingly in order to be correctly model bound on post, you need to use for
loops, that will set the indexes correctly.
Before doing so, you're going to have to tweak your model structure to save your headaches. You need to re-arrange your logic so that you have a hierarchical object model in which you can iterate more cleaner (this way we're getting away from logic in the view too!)
Your survey header class, can't you put a list of subheaders on it? Then your subheader class, can you put the list of questions for that subheader? That way you can do:
@for (var i = 0; i < Model.SurveyHeaders.Count; i++)
{
<h1>@Model.SurveyHeaders[i].Name</h1>
for (var j = 0; j < Model.SurveyHeaders[i].SubHeaders.Count; j++)
{
<h2>@Model.SurveyHeaders[i].SubHeaders[j].Name</h2>
for (var k = 0; k < Model.SurveyHeaders[i].SubHeaders[j].Questions.Count; k++)
{
@Html.RadioButtonFor(x => x.SurveyHeaders[i].SubHeaders[j].Questions[k].Value , 1);
@Html.RadioButtonFor(x => x.SurveyHeaders[i].SubHeaders[j].Questions[k].Value , 2);
@Html.RadioButtonFor(x => x.SurveyHeaders[i].SubHeaders[j].Questions[k].Value , 3);
@Model.SurveyHeaders[i].SubHeaders[j].Questions[k].Question
}
}
}
This assumes your new model structure is something like (with the following classes):
public class MyModel
{
public List<SurveyHeader> SurveyHeaders { get; set; }
}
public class SurveyHeader
{
public string Name { get; set; }
public List<SubHeader> SubHeaders { get; set; }
}
public class SubHeader
{
public string Name { get; set; }
public List<Question> Questions { get; set; }
}
public class Question
{
public int Value { get; set; }
public string Question { get; set; }
}
Also one other tip, for future reference, you use the following LINQ in your code:
x => x.surveyResults.Where(y => y.SurveyQuestionID == question.ID).First().Value
You can simplify it because First
can actually take a lamba, like so (although you should use FirstOrDefault
and null check it in future just for safety):
x => x.surveyResults.First(y => y.SurveyQuestionID == question.ID).Value
Upvotes: 3
Reputation: 4379
You could use the overload of the RadioButtonFor extension that takes in HtmlAttributes and set the name of each of the RadioButtons.
Upvotes: 1