w00
w00

Reputation: 26772

Foreach in BeginForm and display elements in RadioButtonFor() element

I'm using C#.NET MVC3 (Razor) to create a simple form. But in that form i need to print the content of a list in the form of radiobuttons. But i'm not sure how this works:

@using(Html.BeginForm("Method", "Controller", FormMethod.Post))
{
    foreach (Items item in Model.Items)
    {
        <div>
            @Html.RadioButtonFor(item->itemId)
            @Html.LabelFor(item->description)
        </div>
    }
}

But this doesn't work.

I can probably use normal html tags to create the radio buttons. But then the data won't be auto saved in the right?

How can i make this work?

Upvotes: 0

Views: 3651

Answers (3)

Patryk Ćwiek
Patryk Ćwiek

Reputation: 14318

The syntax is a bit different:

@Html.RadioButtonFor(model => item.ItemId)
@Html.LabelFor(model => item.Description)

Everything else looks fine.

[EDIT] Whoa, I must be tired. Yeah, the following looks just fine, but only for display. Check the Darin's answer for editor template.

[EDIT2] It's not quite obvious from the question, but it seems from your comments that the item in the foreach is another Enumerable. Nest the foreach loops then, to display the properties:

@foreach(var itemList in Model.Items)
{
    foreach(var item in itemList)
    {
        <div>
            @Html.RadioButtonFor(model => item.ItemId)
            @Html.LabelFor(model => item.Description)
        <div>
    }
}

Is that it? I'm still not sure if I understand it correctly. :)

Upvotes: 0

Kaf
Kaf

Reputation: 33819

As you are inside foreach loop. following will work.

foreach (Items item in Model.Items)
{
    <div>
        @Html.RadioButtonFor(item.itemId)
        @Html.LabelFor(item.description)
    </div>
}

If you want to save them all you need to implement zero index based solution as follows

@{int i = 0}
foreach (Items item in Model.Items)
{
    <div>
        @Html.RadioButtonFor(model =>model[i].itemId)
        @Html.LabelFor(model =>model[i].description)
    </div>
    i++;
}

Upvotes: 2

Darin Dimitrov
Darin Dimitrov

Reputation: 1038830

I would recommend you using editor templates instead of writing those loops:

@model MyViewModel
@using(Html.BeginForm("Method", "Controller", FormMethod.Post))
{
    @Html.EditorFor(x => x.Items)
}

and now define a corresponding editor template which will automatically be rendered for each element of the model (~/Views/Shared/EditorTemplates/ItemViewModel.cshtml):

@model ItemViewModel
<div>
    @Html.RadioButtonFor(x => x.itemId, "1")
    @Html.LabelFor(x => x.description)
</div>

Notice that you must pass a second argument to the Html.RadioButtonFor helper in addition to the lambda expression that picks the corresponding view model property. This argument represents the value that will be sent to the server and bound to the corresponding property if the user checks this radio button when the form is submitted.

Also notice that this works by convention. If we assume that the Items property in your main view model is of type IEnumerable<ItemViewModel> then the corresponding editor template that you must define and which will be rendered for each element of this collection is ~/Views/Shared/EditorTemplates/ItemViewModel.cshtml or ~/Views/CurrentController/EditorTemplates/ItemViewModel.cshtml if you don't want this template to be shared between multiple controllers.

Upvotes: 6

Related Questions