简体   繁体   English

Knockout.js将对象数组绑定到重复对象 <select>的

[英]Knockout.js bind array of objects to repeated <select>'s

I've got this Knockout.js view model: 我有这个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
    }]
}

And these html <select> s: 这些html <select> 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>

Can anyone tell me what I need to add to the data-bind attributes of each select to tie them up to the Knockout.js view model? 谁能告诉我我需要添加到每个selectdata-bind属性中以将它们data-bind到Knockout.js视图模型吗? The value of the first select should be bound to LanguageFromId in the view model and the value of the second select should be bound to LanguageToId in the view model. 第一个selectvalue应绑定到视图模型中的LanguageFromId ,第二个selectvalue应绑定到视图模型中的LanguageToId

LanguageFromTos in the view model is an array, so all of what you see inside may be repeated (2 LanguageFromTos would result in the LanguageFromToRow div being repeated twice, for example). 视图模型中的LanguageFromTos是一个数组,因此您在内部看到的所有内容都可以重复(例如,2 LanguageFromTos将导致LanguageFromToRow div重复两次)。 The number of repeats is set both server-side (data posted by the controller may have multiple LanguageFromTos ) and client-side (an 'add' button that allows the user to add another div with its contained select s) in different cases, so I presume Knockout's templating is a no-go as MVC needs to loop through and render each row so that it can catch them all on a 'normal' post back. 在不同情况下,服务器端(控制器发布的数据可能具有多个LanguageFromTos )和客户端端(一个“添加”按钮,允许用户添加包含其select的另一个div)均设置重复次数,因此我认为Knockout的模板是一成不变的,因为MVC需要遍历并渲染每一行,以便它可以在“普通”回发中捕获它们。

Any help much appreciated! 任何帮助,不胜感激!

Edit 编辑

Here's the MVC model for the page: 这是页面的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; }
}

Here's the LanguageFromTo object: 这是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; }
}

And here's the cshtml code for the MVC view. 这是MVC视图的cshtml代码。 This code sits in a partial that's repeated depending on how many LanguageFromTo s there are in DirectorySearchModel that's passed to the MVC view: 此代码位于重复的部分中,具体取决于传递给MVC视图的DirectorySearchModel中有多少LanguageFromTo

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

Your design here has some poor choices. 您的设计在这里有一些糟糕的选择。 Knockout's Templating is the right choice for this, but it is going to require you to start thinking in a different sort of pattern. 淘汰赛的模板正确的选择,但这将要求您开始以其他方式进行思考。 You do not need to use partials to accomplish the repetition you are after. 您不需要使用局部函数来完成您要执行的重复。

Here is a fiddle demonstrating a templating solution. 这是一个演示模板解决方案的小提琴。 http://jsfiddle.net/tyrsius/XgwLD/3/ http://jsfiddle.net/tyrsius/XgwLD/3/

Some notes: to populate incomingData , an easy method will be to use @Html.Raw(Json.Encode(Model.DirectorySearchModel )); 一些注意事项:要填充incomingData ,一个简单的方法是使用@Html.Raw(Json.Encode(Model.DirectorySearchModel )); . This will turn your model into a JSON object, which the viewModel's constructor can easily use. 这会将您的模型变成一个JSON对象,viewModel的构造函数可以轻松使用它。

Now, I didn't use any MVC code in the fiddle because I can't, but you've obviously already found how you can put data-bind in the MVC helpers. 现在,我没有使用任何MVC代码,因为我没有使用,但是您显然已经找到了如何将数据绑定放入MVC帮助器中。 This isn't always a bad idea, but for things like selects and DIVs that you want to use as templates, it will probably just makes things harder to read. 这并不总是一个坏主意,但是对于要用作模板的select和DIV之类的东西,可能只会使事情变得更难阅读。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM