剃刀:如果模型列表与LT;>然后@ Html.LabelFor创建emtpy"为"领域 [英] Razor: If model is List<> then @Html.LabelFor creates emtpy "for" field

查看:191
本文介绍了剃刀:如果模型列表与LT;>然后@ Html.LabelFor创建emtpy"为"领域的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果该模型对象的列表,然后 @ Html.LabelFor模型=>模型[I]。成员)创建一个空的属性。
中的显示名称正常工作,模型还结合工作得很好。不工作的唯一的事情是属性。



下面有MVC的代码的两个版本。前3个代码段为模型,控制器和视图组合不起作用,(该模型是一个列表)。第二组3代码片段的工作。这一次的名单被包裹在一个对象。



我在想什么?



模型:

 公共类视图模型{
公布尔ClickMe {搞定;组; }
}



控制器:

 公众的ActionResult LabelForViewModel(){
名单,LT;视图模型>模型=新的List<视图模型>(){
新视图模型(){ClickMe =真}
};
返回查看(模型);
}

查看:

  @model名单< ModelBinding.Models.ViewModel>为简便起见
@for删除
//形式的代码(VAR I = 0; I< Model.Count;我++){
< DIV CLASS =表单组>
@ Html.LabelFor(型号=>模型[I] .ClickMe)
< DIV CLASS =COL-MD-10>
@ Html.EditorFor(型号=>模型[I] .ClickMe,新{htmlAttributes = {新@class =表格控}})
@ Html.ValidationMessageFor(型号= GT;模型[I] .ClickMe,新{@class =TEXT-危险})
< / DIV>
< / DIV>
}



标记:

 < DIV CLASS =表单组> 
<标签=> ClickMe< /标签>
< DIV CLASS =COL-MD-10>
<输入名称=[0] .ClickMe级=的形式控制复选框TYPE =复选框检查=选中价值=真实数据-VAL-所需=的ClickMe字段是必须的。数据-VAL =真正的><输入名称=[0] .ClickMe类型=隐藏值=假>
<跨度类=现场验证,有效文本危险数据valmsg替换=真正的数据valmsg换=[0] .ClickMe>< / SPAN>
< / DIV>
< / DIV>

请注意,在现场为空,且输入有没有id字段(一个是用在在供字段)。



我已经创建了一个包含对象列表的包装模式,修改了控制器和视图,然后它工作得很好。在这种情况下,为字段填写正确,一切都按预期工作。

 公共类ListWrapper {
公开名单<视图模型> {的ViewModels获得;组; }
}

查看:

  @for(VAR I = 0; I< Model.ViewModels.Count;我++){
< DIV CLASS =表单组>
@ Html.LabelFor(型号=> model.ViewModels [I] .ClickMe)
< DIV CLASS =COL-MD-10>
@ Html.EditorFor(型号=> model.ViewModels [I] .ClickMe,新{htmlAttributes = {新@class =表格控}})
@ Html.ValidationMessageFor(型号= > model.ViewModels [I] .ClickMe,新{@class =TEXT-危险})
< / DIV>
< / DIV>
}



标记:

 < DIV CLASS =表单组> 
<标签=ViewModels_0__ClickMe> ClickMe< /标签>
< DIV CLASS =COL-MD-10>
<输入名称=的ViewModels [0] .ClickMe级=的形式控制复选框ID =ViewModels_0__ClickMe类型=复选框检查=选中价值=真实数据-VAL -required =该ClickMe字段是必需的。数据-VAL =真正的><输入名称=的ViewModels [0] .ClickMe类型=隐藏值=假>
<跨度类=现场验证,有效文本危险数据valmsg替换=真正的数据valmsg换=的ViewModels [0] .ClickMe>< / SPAN>
< / DIV>
< / DIV>



所以,似乎属性是空只有当模型是对象的列表。



这是一个已知的问题?或者,也许我失去了一些东西?


解决方案

此行为与HTML-4规格符合该框架的结果。在HTML-4




ID和名称标记必须以字母开头([A-ZA-Z]),并可以跟任何字母数字,数字([0-9]),连字符( - ),下划线(_),冒号(:)和句点(。)




当你的模型是一个集合,并使用 @ Html.EditorFor(M = GT; M [] .SomeProperty)生成表单控件,该方法生成<基于属性的名称code>名称和 ID 属性。在这种情况下,集合中的第一个项目的名称属性将

  NAME =[0] .SomeProperty

但要避免使用jQuery选择冲突的方法替换 [] 以下划线字符 _ 生成 ID 属性,这将导致



<当pre> ID =_ 0__SomeProperty

但根据,因为这是无效的到HTML-4规格,助手不输出它的HTML。



同样使用时 @ Html.LabelFor()适用(因为相关的表单控件不会有一个 ID 属性的值属性是不是在HTML输出。



请注意,在HTML-5, ID 属性将是有效的,所以希望这种行为将在未来被删除。



您第二个例子工程,因为 ID =ViewModels_0__ClickMe 开始与一个字母,因此是有效的。



附注:您可以通过生成自己的 ID解决第一个问题属性,例如:

  @ Html.LabelFor(型号= GT;模型[I] .ClickMe,新{=为的String.Format(项{0},I)})
@ Html.EditorFor(型号=> model.ViewModels [I] .ClickMe,新{ htmlAttributes = {新@class =表格控,ID =的String.Format(项{0},I)}})


If the model is a list of objects then @Html.LabelFor model => model[i].member) creates an empty for attribute. The DisplayName works properly, model binding also works just fine. The only thing that does not work is the for attribute.

Below there are two versions of the MVC code. The first 3 code snippets are for the model, controller and view combination that does not work, (the model is a list). The second set of 3 code snippets work. This time the list is wrapped in an object.

What am I missing?

Model:

public class ViewModel {
    public bool ClickMe { get; set; }
}

Controller:

public ActionResult LabelForViewModel() {
    List<ViewModel> model = new List<ViewModel>() {
        new ViewModel() { ClickMe = true}
    };
    return View(model);
}

View:

@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>
}

Markup:

<div class="form-group">
    <label for="">ClickMe</label>
    <div class="col-md-10">
        <input name="[0].ClickMe" class="form-control check-box" type="checkbox" checked="checked" value="true" data-val-required="The ClickMe field is required." data-val="true"><input name="[0].ClickMe" type="hidden" value="false">
        <span class="field-validation-valid text-danger" data-valmsg-replace="true" data-valmsg-for="[0].ClickMe"></span>
    </div>
</div>

Please notice that the for field is empty and the input has no id field (that one is used in the "for" field).

I have created a wrapper model that contains a list of objects, modified the controller and view and then it works just fine. In this case the "for" field is filled in correctly and everything works as expected.

public class ListWrapper {
    public List<ViewModel> ViewModels { get; set; }
}

View:

@for (var i = 0; i < Model.ViewModels.Count; i++) {
    <div class="form-group">
        @Html.LabelFor(model => model.ViewModels[i].ClickMe)
        <div class="col-md-10">
            @Html.EditorFor(model => model.ViewModels[i].ClickMe, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.ViewModels[i].ClickMe, "", new { @class = "text-danger" })
        </div>
    </div>
}

Markup:

<div class="form-group">
    <label for="ViewModels_0__ClickMe">ClickMe</label>
    <div class="col-md-10">
        <input name="ViewModels[0].ClickMe" class="form-control check-box" id="ViewModels_0__ClickMe" type="checkbox" checked="checked" value="true" data-val-required="The ClickMe field is required." data-val="true"><input name="ViewModels[0].ClickMe" type="hidden" value="false">
        <span class="field-validation-valid text-danger" data-valmsg-replace="true" data-valmsg-for="ViewModels[0].ClickMe"></span>
    </div>
</div>

So, it seems that the for attribute is empty only if the model is a list of objects.

Is this a known issue? Or maybe I'm missing something?

解决方案

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) } })

这篇关于剃刀:如果模型列表与LT;&GT;然后@ Html.LabelFor创建emtpy&QUOT;为&QUOT;领域的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆