Knockout.JS与bootstrap selectpicker

Sam*_*nch 7 javascript twitter-bootstrap knockout.js

我正在尝试使用Bootstrap Selectpicker和knockout.js.已有一个自定义绑定适用于selectpicker的多选版本(见此处),但我需要它才能使用单选版本.我认为这将简单到更改ko.observableArray为a ko.observable和删除multiple属性 - 但似乎并非如此.关于如何使这个工作的任何想法?

摆弄绑定和我更新的代码

Rob*_*ney 13

编辑 请参阅下面的替代解决方案

问题出在你的selectPicker.init函数上.

您需要调用选项绑定,而不是值绑定.options.init设置初始内部状态,当它绕过options.update函数将重置该值.

// regular select and observable so call the default value binding
ko.bindingHandlers.value.init(element, valueAccessor, allBindingsAccessor);
Run Code Online (Sandbox Code Playgroud)

改成

// regular select and observable so call the default value binding
ko.bindingHandlers.options.init(element, valueAccessor, allBindingsAccessor);
Run Code Online (Sandbox Code Playgroud)

编辑

好的,我把你的样本带回基础以使用标准选项绑定来获得正常的选择工作.

然后仅使用selectpicker绑定进行初始化和刷新.它将自己同步到选择.

在Knockout 3之前,如果元素上的任何绑定导致更新(如更新选项,值或selectedOptions),则会调用selectPicker更新函数.使用Knockout 3,绑定现在可以独立启动(好东西),但是当选项或值/ selectedOptions发生更改时,您现在需要使用订阅来获得通知.

我想你会发现现在这个更简单了,你的自定义绑定中的单选和多选之间没有区别.如果更新了teamItems或itemID observable,现在可以使用此功能.

HTML

<!-- Multiple Select -->
<select data-bind="selectedOptions: teamIDs, 
                   options: teamItems, 
                   optionsText: 'text', 
                   optionsValue : 'id', 
                   selectPicker: {}" multiple="true"></select>
Run Code Online (Sandbox Code Playgroud)

JAVASCRIPT

ko.bindingHandlers.selectPicker = {
  after: ['options'],   /* KO 3.0 feature to ensure binding execution order */
  init: function (element, valueAccessor, allBindingsAccessor) {
     var $element = $(element);
     $element.addClass('selectpicker').selectpicker();

     var doRefresh = function() {
         $element.selectpicker('refresh');
     },  subscriptions = [];

     // KO 3 requires subscriptions instead of relying on this binding's update
     // function firing when any other binding on the element is updated.

     // Add them to a subscription array so we can remove them when KO
     // tears down the element.  Otherwise you will have a resource leak.
     var addSubscription = function(bindingKey) {
         var targetObs = allBindingsAccessor.get(bindingKey);

         if ( targetObs && ko.isObservable(targetObs )) {
            subscriptions.push( targetObs.subscribe(doRefresh) );
         }
     };

     addSubscription('options');
     addSubscription('value');           // Single
     addSubscription('selectedOptions'); // Multiple

     ko.utils.domNodeDisposal.addDisposeCallback(element, function() { 
         while( subscriptions.length ) {
             subscriptions.pop().dispose();
         }
     } );
   },
   update: function (element, valueAccessor, allBindingsAccessor) {
   }
 };
Run Code Online (Sandbox Code Playgroud)


M.S*_*amm 5

Knockout 对计算绑定(例如item().children.length > foo().maxChildren)具有出色且强大的支持,而当前的答案无法支持这些。

因此,为了进一步改进 RobertSlanley 的答案,并根据Knockout 的文档,我创建了以下绑定。

只要我们在 update 方法中访问它们,Knockout 就会自行处理可观察的订阅。这意味着我们可以消除订阅的烦恼,只专注于我们真正想做的事情:

ko.bindingHandlers.selectPicker = {
    after: ['options', 'value', 'selectedOptions'],
    init: function (element, valueAccessor, allBindingsAccessor) {
        $(element).addClass('selectpicker').selectpicker();
    },
    update: function (element, valueAccessor, allBindingsAccessor) {
        /* KO 3.3 will track any bindings we depend on
           and call us when any of them changes */
        allBindingsAccessor.get('options');
        allBindingsAccessor.get('value');
        allBindingsAccessor.get('selectedOptions');

        $(element).selectpicker('refresh');
    }
};
Run Code Online (Sandbox Code Playgroud)

这是一个演示小提琴