If the model is a list of objects then @Html.LabelFor model => model[i].member)
creates an empty for
attribute.
The DisplayName works properly,
This behavior is the result of the framework complying with HTML-4 specifications. In HTML-4
ID and NAME tokens must begin with a letter ([A-Za-z]) and may be followed by any number of letters, digits ([0-9]), hyphens ("-"), underscores ("_"), colons (":"), and periods (".").
When your model is a collection and you use @Html.EditorFor(m => m[i].SomeProperty)
to generate form controls, the method generates name
and id
attributes based on the name of the property. In this case the name
attribute for the first item in the collection will be
name="[0].SomeProperty"
but to avoid clashes with jQuery selectors, the method replaces .
, [
, and ]
characters with an underscore _
when generating the id
attribute which would result in
id="_0__SomeProperty"
but because this is invalid according to the HTML-4 specification, the helper does not output it in the html.
The same applies when using @Html.LabelFor()
(since the associated form control will not have an id
attribute, the value of the for
attribute is not output in the html.
Note that in HTML-5, the id
attribute would be valid, so hopefully this behavior will be dropped in the future.
Your second example works because id="ViewModels_0__ClickMe
" begins with a letter and is therefore valid.
Side note: You could solve the first issue by generating your own id
attributes, for example
@Html.LabelFor(model => model[i].ClickMe, new { for = string.Format("item{0}", i) })
@Html.EditorFor(model => model.ViewModels[i].ClickMe, new { htmlAttributes = new { @class = "form-control", id = string.Format("item{0}", i) } })
The @model declaration assigns the model object to the Model
variable (note the captial 'M'). But then you are reading from model
, which hasn't been assigned.
Try this:
@model List<ModelBinding.Models.ViewModel>
// form code removed for brevity
@for (var i = 0; i < Model.Count; i++) {
<div class="form-group">
@Html.LabelFor(model => Model[i].ClickMe)
<div class="col-md-10">
@Html.EditorFor(model => Model[i].ClickMe, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => Model[i].ClickMe, "", new { @class = "text-danger" })
</div>
</div>
}
That doesn't explain why your second example works at all, but hey, give this a try.