How to use EditorFor inside a foreach
Asked Answered
O

3

39

I have a model:

public class MyListModel
{
    public int ID {get;set;}
    public List<User> Users{get;set;}
}

How do I use the Html.EditorFor method inside a foreach?

@model MyListModel
<table>
  <tr>
    <th></th>
  </tr>
  @foreach (var item in Model.Users) {
     <tr>
       <td>
          @Html.EditorFor(item.Enabled)
       </td>
     </tr>
  }
</table>
Orme answered 31/12, 2009 at 5:2 Comment(0)
Y
67
@Html.EditorFor(x=> item.Enabled)

It's been pointed out many times that posting such a model back to server will not work in mvc by default. For properly editing with EditorFor in a loop - for should be used as in:

 @for(var i = 0; i< Model.Users.Count;i++){
      Html.EditorFor(i=>Model.Users[i])
 }
Yt answered 1/1, 2010 at 0:35 Comment(11)
Definitely works. The "right hand side" of a lambda does not have to reference the "left hand side".Supersensible
Well gee, would you look at that! That will clean up some of the Html.RenderPartial()s I've been using unnecessarily.Dapsang
You're right, it does work. I didn't think it would either. Thanks.Orme
Keep in mind that lambdas are just method definition. A method can take a parameter "x" and not actually use it in the method body. A neat trick, for sure! I highly recommend reading Brad Wilson's 5-part series on templated helpers: bradwilson.typepad.com/blog/2009/10/…Supersensible
I never realized that about lambdas; where have I been all this time?!Dapsang
So in this case, x is a parameter of the method definition, item.enabled is the body, what type is x?Orme
x is of the same type as model.Yt
Note that this will cause all elements created by the EditorFor to have the same name and Id. It's not valid for multiple elements to share the same Id.Bergess
This will work to display the properties, but it will not bind properly on postback for the reason that @DaRKoN_ mentioned. The DefaultModelBinder has no idea how to bind the unindexed properties with duplicate names. The names are what MVC uses to map the values from the request to the properties of your model.Incite
This solution is working, but will lost the bindings when you post the form back to the server. So the best method is to use a simple for loop.Falito
Not really sure why this is the accepted answer if it loses bindings when posted back to the server.Hildebrandt
C
15
@for (var i = 0; i < Model.Users.Count; i++)
{
<tr>
    <td>@Html.EditorFor(model => model.Users[i].Enabled)</td>
    <td>@Html.EditorFor(model => model.Users[i].FirstName)</td>
    <td>@Html.EditorFor(model => model.Users[i].LastName)</td>
</tr>
}

Plus some hidden variables for at least one property of the User are required:

@for (var i = 0; i < Model.Users.Count; i++)
{
    @Html.HiddenFor(model => model.Users[i].FirstName)
}

Not what you would call elegant but it works with respect to binding in your post action.

Coats answered 26/11, 2013 at 6:29 Comment(0)
S
1

Is there any other reason (example apart) for explicitly using the foreach yourself? You could make a Custom Editor (or Display) helper for User class and make @Html.EditorFor(model=>model.Users). Razor will use the foreach internally for processing each element with your Custom Helper.

Just an idea for those visiting the question with really no clue how manage this cases.

Sennet answered 14/4, 2016 at 2:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.