Knockout.JS与引导程序selectpicker



我正试图将Bootstrap Selectpicker与knockout.js一起使用。已经有一个自定义绑定适用于Selectpicker的多选版本(如图所示),但我需要它来处理单选版本。我原以为它会像将ko.observableArray更改为ko.observable并删除multiple属性一样简单,但事实并非如此。有什么想法可以让它发挥作用吗?

摆弄绑定和我更新的代码

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

问题出在selectPicker.init函数上。

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

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

更改为

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

编辑

好的,我带您回到了使用标准选项绑定的基础示例,以使正常的选择工作。

然后仅使用selectpicker绑定进行初始化和刷新。它将自行与select同步。

在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>

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) {
}
};

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

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

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');
}
};

这是一个演示小提琴

不幸的是,我还不能对上面的答案发表评论,但HTML部分有一个小错误:

所选的值绑定应该是selectedOptions,而不是selectOptions

HTML

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

最新更新