0

I am trying to use EditorFor to enter values into a list within a view model. I don't want every element in the list to allow edits though. The method of determining which element in the list can be edited is by using an additional list in my view model. The two lists line up perfectly so at the i'th position of one list exactly corresponds to the i'th position of the other. The code is as follows:

<div class="form-group">
        @Html.Label("Inputs", htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @for (int i = 0; i < Model.InputList.Count(); i++)
            {
                @Html.Label(i + 1 + ") " + Model.ProtocolSteps[i].Description)
                if (Model.ProtocolSteps[i].InputNeeded.Value)
                {
                    @Html.EditorFor(model => model.InputList[i], new { htmlAttributes = new { @class = "form-control" } })
                }
                <br />
            }
        </div>
    </div>

The ProtocolSteps list determines if an editorfor template should be displayed. If it should, the editorfor input is stored into the InputList. This code works perfectly without the if statement (i.e. all values are stored to the correct location in InputList). With the if statement, the view is displayed perfectly, but values are not stored into InputList (usually one value is stored into the list, but not all). Any help is appreciated with why the if statement is messing things up.

Tieson T.
  • 20,774
  • 6
  • 77
  • 92
Jon
  • 278
  • 8
  • 23

1 Answers1

0

Edit

Took this offline and we found that ASP.NET needed it to always write out the value, so adding a hidden field seems to work. But if anyone happens by this post, it'd be nice if you could explain why this is required.

@Html.Label(i + 1 + ") " + Model.ProtocolSteps[i].Description)
if (Model.ProtocolSteps[i].InputNeeded.Value)
{
   @Html.EditorFor(model => model.InputList[i], new { htmlAttributes = new { @class = "form-control" } })
}
else 
{
   @Html.HiddenFor(model => model.InputList[i]);
}

Was just watching a microsoft video about this, they said that when using the @Html helpers within an iteration, you need to refer directly to the list, and not the value passed into the lambda expression. So, try changing to:

@Html.EditorFor(i => Model.InputList[i], new { htmlAttributes = new { @class = "form-control" } })

EDIT Looks like a similar problem over here. How to use EditorFor inside a foreach

I updated my previous entry to match, but I haven't tested this. Seems like the other guy did cause it got a lot of upvotes.

Community
  • 1
  • 1
Jamieson Rhyne
  • 428
  • 3
  • 10
  • Thanks for the response, but it did not change anything. I'm still getting the same result. Any other suggestions? – Jon Jul 17 '15 at 19:02
  • Edited the answer, not sure why it works, but according to that linked question it should. – Jamieson Rhyne Jul 17 '15 at 19:19
  • What if you moved the label into the if statement? – Jamieson Rhyne Jul 17 '15 at 19:25
  • I get compilation errors with this since I'm already using i for my loop variable. – Jon Jul 17 '15 at 19:32
  • Moving the label didn't help, plus I need it outside of the if statement – Jon Jul 17 '15 at 19:33
  • I wouldn't think that would matter either. – Jon Jul 17 '15 at 19:34
  • you already said it works without the if statement, does your code as-is work if you replaced the if statement with something like if (i%2 == 0)? – Jamieson Rhyne Jul 17 '15 at 19:36
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/83579/discussion-between-jamieson-rhyne-and-jon). – Jamieson Rhyne Jul 17 '15 at 19:37
  • 1
    It required because collection indexers must start at zero and be consecutive in order to be bound by the `DefaultModelBinder`. You can also handle this by including a special hidden input - `` –  Jul 18 '15 at 01:39