【问题标题】:Knockout js: Lazy load options for selectKnockout js:选择的延迟加载选项
【发布时间】:2013-04-17 15:12:44
【问题描述】:

我正在尝试使用淘汰赛 js 创建一个延迟加载选择。多亏了淘汰赛,按需加载数据并让它更新 UI 变得很简单。但是,一旦加载数据,我在设置正确的项目时遇到问题。

示例 jsFiddle here

经过一番挖掘,它似乎会覆盖该值,因为它希望将模型与选项相匹配。请参阅 knockout-2.2.1.debug.js 中的“ensureDropdownSelectionIsConsistentWithModelValue”。

这对我来说是个问题,因为在它执行此操作时,没有任何选项,因此它会用 0 覆盖我的模型值。

我对淘汰赛还很陌生,所以我怀疑我正在接近这个错误......有人做到了吗?还是有更好的建议?

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

提前感谢您的帮助:)

Ste.

代码示例:

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());

【问题讨论】:

    标签: javascript knockout.js lazy-loading


    【解决方案1】:

    一般来说,我处理这种情况的方法是预先填充 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/

    【讨论】:

    • 感谢 Ryan,我认为这是我一直在寻找但无法完全确定的方法。与 Sujesh 相比,这种方法的优势在于您不会在填充时间之间丢失模型值。这样,如果给定的下拉列表无法填充并且用户保存了一些其他更改,则将保留现有值。
    • 如果我有两个或多个选择不同的数据会怎样..?
    【解决方案2】:

    这是一个邪恶的老问题,但我想我会为了其他任何出现并发现这个问题的人而发帖。我编写了一个插件来封装可供选择对象使用的选项及其所选索引。

    这个插件还解决了上面描述的原始问题,因为您可以将一个值加载到 observable 中,然后在稍后加载选项,并且如果该值存在于加载的列表中,那么 observable 将自动连接它.

    看看,希望这对这些年后来的人有帮助:)

    https://github.com/ozrevulsion/KoSelectSugar

    【讨论】:

      【解决方案3】:

      这是一个更新的小提琴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);
          });  
      };
      

      【讨论】:

      • 谢谢,我想我用计算出的 observables 想太多了,并试图阻止它清除我的模型值!我已经将您的建议打包成一种方法,因为我有很多要创建的方法。更新小提琴here.
      猜你喜欢
      • 2012-04-07
      • 2010-11-04
      • 2014-08-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-17
      • 1970-01-01
      相关资源
      最近更新 更多