【问题标题】:Knockout.js bind array of objects to repeated <select>'sKnockout.js 将对象数组绑定到重复的 <select> 的
【发布时间】:2012-05-31 13:36:55
【问题描述】:

我有这个 Knockout.js 视图模型:

{
    "LanguageFromTos":
    [{
        "LanguageFromToId":0,
        "LanguageFromId":2,
        "LanguageFrom":null,
        "AllLanguagesFrom":[
            {"Selected":false,"Text":"English","Value":"1"},
            {"Selected":false,"Text":"French","Value":"2"},
            {"Selected":false,"Text":"Spanish","Value":"3"}
        ],

        "LanguageToId":1,
        "LanguageTo":null,
        "AllLanguagesTo":[
            {"Selected":false,"Text":"English","Value":"1"},
            {"Selected":false,"Text":"French","Value":"2"},
            {"Selected":false,"Text":"Spanish","Value":"3"}
        ],
        "Users":null
    }]
}

还有这些 html &lt;select&gt;s:

<div class="LanguageFromToRow">
    <input type="hidden" name="languageFromTos.index" autocomplete="off" value="c50532b0-65d2-4a81-baeb-59b768fd120f" />

    <label for="languageFromTos_c50532b0-65d2-4a81-baeb-59b768fd120f__LanguageFromId">From</label>:
    <select data-bind="???" data-val="true" data-val-number="The field From must be a number." data-val-required="The From field is required." id="languageFromTos_c50532b0-65d2-4a81-baeb-59b768fd120f__LanguageFromId" name="languageFromTos[c50532b0-65d2-4a81-baeb-59b768fd120f].LanguageFromId">
        <option value="1">English</option>
        <option selected="selected" value="2">French</option>
        <option value="3">Spanish</option>
    </select>
    <span class="field-validation-valid" data-valmsg-for="languageFromTos[c50532b0-65d2-4a81-baeb-59b768fd120f].LanguageFromId" data-valmsg-replace="true"></span>

    <label for="languageFromTos_c50532b0-65d2-4a81-baeb-59b768fd120f__LanguageToId">To</label>:
    <select data-bind="???" data-val="true" data-val-number="The field To must be a number." data-val-required="The To field is required." id="languageFromTos_c50532b0-65d2-4a81-baeb-59b768fd120f__LanguageToId" name="languageFromTos[c50532b0-65d2-4a81-baeb-59b768fd120f].LanguageToId">
        <option selected="selected" value="1">English</option>
        <option value="2">French</option>
        <option value="3">Spanish</option>
    </select>
    <span class="field-validation-valid" data-valmsg-for="languageFromTos[c50532b0-65d2-4a81-baeb-59b768fd120f].LanguageToId" data-valmsg-replace="true"></span>

    <a href="#" class="deleteLanguageFromTo">delete</a>
</div>

谁能告诉我需要添加到每个selectdata-bind 属性以将它们绑定到Knockout.js 视图模型?第一个selectvalue 应该绑定到视图模型中的LanguageFromId,第二个selectvalue 应该绑定到视图模型中的LanguageToId

视图模型中的LanguageFromTos 是一个数组,因此您在里面看到的所有内容都可能重复(例如,2 LanguageFromTos 将导致LanguageFromToRow div 重复两次)。重复次数设置在服务器端(控制器发布的数据可能有多个LanguageFromTos)和客户端(一个“添加”按钮,允许用户添加另一个包含selects的div)不同的情况,所以我认为 Knockout 的模板是不行的,因为 MVC 需要循环并渲染每一行,以便它可以在“正常”回传中捕获它们。

非常感谢任何帮助!

编辑

这是页面的 MVC 模型:

public class DirectorySearchModel
{
    [Display(Name = "User name contains")]
    public string UserName { get; set; }

    [Display(Name = "First name contains")]
    public string FirstName { get; set; }

    [Display(Name = "Last name contains")]
    public string LastName { get; set; }

    [Display(Name = "Languages translated")]
    public IEnumerable<LanguageFromTo> LanguageFromTos { get; set; }
}

这是LanguageFromTo 对象:

public class LanguageFromTo
{
    [Key]
    public virtual int LanguageFromToId { get; set; }

    [Display(Name = "From")]
    public virtual int LanguageFromId { get; set; }
    [ForeignKey("LanguageFromId")]
    public virtual Language LanguageFrom { get; set; }
    public virtual IEnumerable<SelectListItem> AllLanguagesFrom { get; set; }

    [Display(Name = "To")]
    public virtual int LanguageToId { get; set; }
    [ForeignKey("LanguageToId")]
    public virtual Language LanguageTo { get; set; }
    public virtual IEnumerable<SelectListItem> AllLanguagesTo { get; set; }

    public virtual ICollection<User> Users { get; set; }
}

这是 MVC 视图的 cshtml 代码。此代码位于部分重复,具体取决于传递给 MVC 视图的 DirectorySearchModel 中有多少 LanguageFromTos:

<div class="LanguageFromToRow">
    @using(Html.BeginCollectionItem("languageFromTos")) {
        @: @Html.LabelFor(m => m.LanguageFromId): @Html.DropDownListFor(m => m.LanguageFromId, Model.AllLanguagesFrom, new { data_bind = "value: getLanguageFromToById(0).LanguageFromId" }) @Html.ValidationMessageFor(m => m.LanguageFromId)
        @: @Html.LabelFor(m => m.LanguageToId): @Html.DropDownListFor(m => m.LanguageToId, Model.AllLanguagesTo, new { data_bind = "value: getLanguageFromToById(0).LanguageToId" }) @Html.ValidationMessageFor(m => m.LanguageToId)
        <a href="#" class="deleteLanguageFromTo">delete</a>
    }
</div>

【问题讨论】:

  • 如果你能稍微精简一下 HTML 会有所帮助。这么长的标识符是怎么回事?
  • @SystemParadox 感谢您的回复 - 我已经添加了传递给页面的 mvc 模型(并且我想用 Knockout.js 发回)和吐出部分的代码可怕的标识符。

标签: asp.net-mvc asp.net-mvc-3 asp.net-mvc-2 knockout.js knockout-mapping-plugin


【解决方案1】:

你的设计有一些糟糕的选择。 Knockout 的模板 的正确选择,但它需要您开始以不同的模式思考。您不需要使用分词来完成您所追求的重复。

这是一个演示模板解决方案的小提琴。 http://jsfiddle.net/tyrsius/XgwLD/3/

一些注意事项:要填充incomingData,一个简单的方法是使用@Html.Raw(Json.Encode(Model.DirectorySearchModel ));。这会将您的模型转换为 JSON 对象,viewModel 的构造函数可以轻松使用该对象。

现在,我没有在小提琴中使用任何 MVC 代码,因为我不能,但是您显然已经找到了如何将 data-bind 放入 MVC 帮助程序中。这并不总是一个坏主意,但是对于您想用作模板的选择和 DIV 之类的东西,它可能只会让事情变得更难阅读。

【讨论】:

  • 谢谢@Tyrsius!我有点担心这意味着我无法通过更常见的提交按钮回帖到 MVC,但它很管用,再次感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-01-31
  • 1970-01-01
  • 1970-01-01
  • 2012-04-08
  • 2020-04-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多