Razor: If model is List<> then @Html.LabelFor creates empty “for” field

前端 未结 2 1324
Happy的楠姐
Happy的楠姐 2021-01-20 09:03

If the model is a list of objects then @Html.LabelFor model => model[i].member) creates an empty for attribute. The DisplayName works properly,

相关标签:
2条回答
  • 2021-01-20 09:40

    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) } })
    
    0 讨论(0)
  • 2021-01-20 09:49

    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.

    0 讨论(0)
提交回复
热议问题