我正在尝试使用Bootstrap Selectpicker和knockout.js。已经存在一个适用于selectpicker(seen here)的多选版本的自定义绑定,但是我需要它才能使用单一选择版本。我认为这就像将ko.observableArray
更改为ko.observable
并删除multiple
属性一样简单 - 但似乎并非如此。关于如何使这个工作的任何想法?
答案 0 :(得分:13)
编辑请参阅下面的备用解决方案
问题在于你的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绑定进行初始化和刷新。它将自己与选择同步。
在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) {
}
};
答案 1 :(得分:2)
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');
}
};
),当前的答案无法支持这些。
为了进一步改进RobertSlanley的答案,并基于Knockout's documentation,我创建了以下绑定。
只要我们在update方法中访问它们,Knockout就会自己处理可观察的订阅。 这意味着我们可以删除订阅,只关注我们真正想做的事情:
{{1}}
答案 2 :(得分:0)
不幸的是我还不能对上述答案发表评论,但HTML部分有一点错误:
选定的值绑定应为selectedOptions
而不是selectOptions
。
<!-- Multiple Select -->
<select data-bind="selectedOptions: teamIDs,
options: teamItems,
optionsText: 'text',
optionsValue : 'id',
selectPicker: {}" multiple="true"></select>