Knockout js:选择的延迟加载选项

时间:2013-04-17 15:12:45

标签: javascript knockout.js lazy-loading

我正在尝试使用knockout js创建一个延迟加载选择。由于淘汰赛,按需加载数据并让它更新UI非常简单。但是,在加载数据后,我遇到了设置正确项目的问题。

示例jsFiddle here

经过一些挖掘后,看来淘汰会覆盖该值,因为它希望将模型与选项相匹配。请参阅' ensureDropdownSelectionIsConsistentWithModelValue'在knockout-2.2.1.debug.js。

这对我来说是一个问题,因为在这一点上,它没有选项,所以它用0覆盖我的模型值。

我是一个相当新的淘汰赛所以我怀疑我正在接近这个错误......有没有人实现这一目标?还是有更好的建议方法?

我已经阅读了Ryan的博客文章Lazy Loading an Observable in KnockoutJS,但我找不到一种方法来利用他的方法来解决我的问题。

提前感谢您的任何帮助:)

步骤。

代码示例:

HTML:

<select data-bind="options: $data.choice.options, optionsText: 'text', optionsValue: 'value', value: $data.choice"></select>

JS:

var optionsProvider = (function () {
"use strict";
var self = {};
//container for options data, a sort of dictionary of option arrays.
self.options = {};

self.init = function (optionData) {
    //pre-populate any provided options data here...
};

self.get = function(name) {
    if (!self.options[name]) {
        self.options[name] = ko.observable([]);

        //ajax request for options
        //populate self.options[name] with options upon return
        //dummy this with below for example.
        setTimeout(function() { 
            self.options[name]([
                { text : "option1", value : 1 },
                { text : "option2", value : 2 },
                { text : "option3", value : 3 },
            ]); 
        }, 1000); //simulate some delay
    }
    //return reference to observable immediately.
    return self.options[name];
};

return self;
})();


var simpleModel = function() {
    this.choice = ko.observable(2); //hard code selected option to simulated pre-saved selection.
    this.choice.options = optionsProvider.get("SomeOptionType");  
};

ko.applyBindings(new simpleModel());

3 个答案:

答案 0 :(得分:3)

通常,我如何处理这种情况是使用当前值作为唯一项目预先填充observableArray。

对于你,你可能会在你的getter中接受一个initialValue,如:

self.get = function(name, initialValue) {
    if (!self.options[name]) {
        self.options[name] = ko.observableArray([{ value: initialValue }]);

        //ajax request for options
        //populate self.options[name] with options upon return
        //dummy this with below for example.
        setTimeout(function() { 
            self.options[name]([
                { text : "option1", value : 1 },
                { text : "option2", value : 2 },
                { text : "option3", value : 3 },
            ]); 
        }, 1000); //simulate some delay
    }
    //return reference to observable immediately.
    return self.options[name];
};

并将其传递给:

var simpleModel = function() {
  var initialValue = 2;
  this.choice = ko.observable(initialValue); //hard code selected option to simulated pre-saved selection.
  this.choice.options = optionsProvider.get("SomeOptionType", initialValue);  
};

以下是一个示例:http://jsfiddle.net/rniemeyer/sHB9p/

对于稍微更通用的方式,我使用了自定义绑定来实现类似:

ko.bindingHandlers.populateInitialValue = {
    init: function(element, valueAccessor, allBindingsAccessor) {
       var bindings = allBindingsAccessor(),
           options = ko.utils.unwrapObservable(bindings.options),
           optionsValue = bindings.optionsValue,
           value = ko.utils.unwrapObservable(bindings.value),
           initialValue;

        if (options && !options.length) {
            if (optionsValue) {
                initialValue = {};
                initialValue[optionsValue] = value;
            }
            else {
                initialValue = value;   
            }

            bindings.options.push(initialValue);
        }
    }
};

然后,使用它(不对代码进行其他更改):

<select data-bind="populateInitialValue: true, options: $data.choice.options, optionsText: 'text', optionsValue: 'value', value: $data.choice"></select>

这只是查看其他选项并构建初始值。

示例:http://jsfiddle.net/rniemeyer/SmSC6/

答案 1 :(得分:1)

这是一个邪恶的老问题,但我想我会张贴为其他任何人的利益并发现这一点。我编写了一个插件来封装选择对象可用的选项及其选定的索引。

此插件还解决了上述原始问题,因为您可以将值加载到observable中,然后在以后加载选项,如果该值存在于加载的列表中,则observable会自动将其挂起

看看,希望这可以帮助所有这些年来的所有人:)

https://github.com/ozrevulsion/KoSelectSugar

答案 2 :(得分:0)

这是一个更新的小提琴http://jsfiddle.net/sujesharukil/5YFry/5/

您可以订阅对选项的更改,然后设置值,这是一种简单的方法。

var simpleModel = function() {
    var self = this;
  this.choice = ko.observable(2); //hard code selected option to simulated pre-saved     selection.
  this.choice.options = optionsProvider.get("SomeOptionType");  
    this.choice.options.subscribe(function(newValue){
        self.choice(2);
    });  
};