将observableArray映射到基于另一个json数组的多个SELECT

时间:2014-05-12 14:22:33

标签: javascript jquery json knockout.js

3我使用jquery到$ .getJSON并使用此信息填充SELECT下拉列表(<OPTION>的值为ItemID,文本为DisplayName):

//$.getJSON and populate <SELECT> options with this info
{"ItemOptions": [
 {"ItemID" : 1, "DisplayName": "Apples"},
 {"ItemID" : 2, "DisplayName": "Bananas"},
 {"ItemID" : 3, "DisplayName": "Oranges"},
 {"ItemID" : 4, "DisplayName": "Grapes"},
 {"ItemID" : 5, "DisplayName": "Carrots"},
 {"ItemID" : 6, "DisplayName": "Crushed Dreams"}
]}

稍后在代码中,我收到一份货物&#34;清单&#34;,其中包含一些信息,其中包括已发货的清单,如下所示:

//manifest
{
    "LocationSource"    : "Dallas",
    "LocationDestination"   : "New York",
    "Items" : [
        {"ItemID" : 2},
        {"ItemID" : 3},
        {"ItemID" : 6}
    ],
    "Status" : "In Transit"
}
// then ko.mapping.toJS(manifest) and 
// ko.applyBindings(manifest) is done in javascript.

您会注意到清单中的Items数组有ItemID - 与ItemID匹配,我已经填充了SELECT。

我使用Knockout的映射插件 - 只有ko.mapping.fromJS(manifest) - 效果很好。 INPUT和SPAN以及我映射LocationSource,Status等的地方都很棒。

我的问题是我希望SELECT成为一个倍数,并代表我的清单中的项目(添加/删除它们的能力)。 HTML就像:

<input data-bind="value: LocationSource"/>
<input data-bind="value: LocationDestination"/>
<select multiple="multiple" data-bind="value: Items"></select>   // this thing

<select multiple="multiple" data-bind="value: Items().ItemID"></select>

似乎并没有为我剪掉它,我似乎无法弄清楚如何让它正常工作(似乎ko.mapping Items设置为数组,但是当我在SELECT框中进行选择时,它会爆炸(保持原样,或者从函数更改为直值,具体取决于我如何修改码)。

基本上,我的问题是:

我有一个&#34;事物&#34;的列表。它们的ID与我的清单中的数组匹配,该数组是ko.mapped(并且可能是该属性的.observableArray)。如何在我的Items基础上添加或删除&#34;事物&#34; (ItemOptions) - 这样当我将ko.map.toJS(manifest)推回到服务器时,我的Items数组仍然是一个ItemID列表,代表我在SELECT中选择的内容。

编辑:我已经看过将整个列表添加为清单中的.AllItems,就像它们在Knockout examples(self.AvailableMeals)中显示的那样,但那真的不是什么我想 - 当我map.toJS和$ .post回来时,我也不希望将整个列表推回服务器。

更新

self.AllItems = ItemOptions;                                    //doesn't need to change, dont obvserable it, right?
self.Items = ko.observableArray(model.Items);   

然后,在HTML中我有:

<select data-bind="options: AllItems,  optionsText: 'DisplayName', selectedOptions: Items" size="15" multiple="true"></select>

这让我在那里,非常接近。它像我期望的那样操纵清单 - 现在唯一的问题是当我第一次加载清单并应用绑定时,SELECT不会自动选择清单中的项目。我怀疑这是因为Items数组条目和ItemOptions条目不相同?它们都有ItemID,但是一个有DisplayName,另一个没有。

更新2

添加了一个jsfiddle:它将证明它有效,但是没有选择初始加载:

http://jsfiddle.net/85Pvz/1

1 个答案:

答案 0 :(得分:1)

如果我正确理解了您的问题,您想使用selectedOptions binding

所以你有类似的东西:

 <select data-bind="options: ItemOptions, selectedOptions: (manifest.)Items, optionsText: 'name', optionsValue: 'id'" size="5" multiple="true"></select> 

和你的javascript类似:

ItemOptions = [
    {name: "opt1", id: 1},
    {name: "opt2", id: 2},
    {name: "opt3", id: 3},
    {name: "opt4", id: 4} 
]

jsFiddle example