【问题标题】:Mapping observableArray to Multiple SELECT based off another json array基于另一个 json 数组将 observableArray 映射到 Multiple SELECT
【发布时间】:2014-05-13 03:06:52
【问题描述】:

3我使用 jquery 来 $.getJSON 并使用此信息填充 SELECT 下拉列表(<OPTION>s 的值是 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"}
]}

稍后在代码中,我得到一个装运“清单”,其中包含一些信息,其中包括已装运的物品列表,如下所示:

//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 - 与我在 SELECT 中填充的 ItemID 匹配。

我使用 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 设置@987654333 @ 到一个数组,但是每当我在 SELECT 框中进行选择时,它都会爆炸(要么保持初始化时的状态,要么从函数更改为直接值,这取决于我如何修改代码)。

基本上,我的问题是这样的:

我有一个“事物”列表。它们的 ID 与我的清单中的 ko.mapped 数组匹配(并且应该是该属性的 .observableArray)。如何根据“事物”(ItemOptions)列表从我的Items 添加或删除 - 这样当我将ko.map.toJS(manifest) 推回服务器时,我的 Items 数组仍将是 ItemIDs 代表的列表我在 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

【问题讨论】:

    标签: javascript jquery json knockout.js


    【解决方案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

    【讨论】:

    • 这是正确的道路。我到了那里,除了我的清单中的项目只有一个数字数组,没有 ItemID 标签 - 当我开始点击时。它也没有预先选择它们。我怀疑这是因为 Items 中的内容和 ItemOptions 中的内容是相同风格的数组?
    • 如果你省略了optionsValue 参数,你会得到整个对象,see here
    • 我能够做到这一点 - 效果很好,它给了我想要的标签。现在我唯一的问题是,当我最初加载清单(应用绑定)时,SELECT 不是:选择清单中的选择(可能是因为它们不是相似的数组,一个只有 ItemID 另一个有 ItemID 和 DisplayName)。简而言之,在我上面的示例中——在 SELECT 中没有选择项目 2、3、6。有什么想法吗?
    • 我已经更新了我的原始帖子,以反映它现在的位置,在加载和应用绑定时开始工作但没有选择项目。如果我单击 SELECT,它会正确填充 Items,但在初始加载时,它不会选择它已经拥有的内容。
    • 问题是,在 javascript 中,对象 {"ItemId":1, "DisplayName": "Apples"} != object {"ItemID":1, "DisplayName": "Apples"}。这就是您要指定 optionsValue 参数的原因,因为您已经给了 knockoutjs 一个“键”来比较是否相等。这样您就可以设置 self.SelectedItems([1,2,3]) ,它将选择多选中的那些。但是如果你真的需要将你的 id 作为对象,你可以添加一个订阅 SelectedItems,并让那个更新 Items 对象,like so
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-24
    • 2015-07-14
    • 2017-05-26
    • 1970-01-01
    • 1970-01-01
    • 2018-08-14
    相关资源
    最近更新 更多