我使用 select2 和 knockoutJs 进行这个简单的绑定(bind):
ko.bindingHandlers.select2 = {
init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
var options = ko.toJS(valueAccessor()) || {};
setTimeout(function () {
$(element).select2(options);
}, 0);
}
};
标记:
<select class="select2" style="width:100%" data-bind="optionsCaption: '',options: $root.items,optionsText: 'description',optionsValue: 'id', value: $root.selectedItem,select2: { placeholder: 'Select an item...',allowClear: true }"></select>
它有效!现在,我在 Select2 中启用了 allowClear
选项,以清除下拉列表中的占位符值,例如 Select an item...
。
如果我单击 x
图标下拉列表,则会正确设置占位符,但 knockout 不会更新可观察的绑定(bind)值!
我想我必须更改自定义绑定(bind),添加如下内容:
setTimeout(function () {
$(element).select2(options).on("select2-removed", function (e) {
ko.bindingHandlers.value.update(element, function () { return ''; });
});
...
但这行不通!
最佳答案
有几个问题。
1) update
在绑定(bind)处理程序中是根据值变化更新DOM,你永远不应该定义 update
能够改变模型的回调。
正确的方法是,定义新的绑定(bind)处理程序时,使用 init
连接所有的回调 change
与模型发生的事件,update
回调只是一个 DOM 绘制例程。
如果您的init
提供的DOM绘图(例如select2提供的),不需要定义update
回调。
因此行 ko.bindingHandlers.value.update(element, function () { return ''; });
只重绘 DOM,它不会做你想要的事情。
2) select2
您创建的绑定(bind)有一些漏洞。
- 首先,
value
绑定(bind)不知道select2
的存在绑定(bind),这就是你挣扎的地方。 - 第二,你的
select2
绑定(bind)必须等待其他绑定(bind)(options
绑定(bind))完成DOM创建,这就是为什么你使用setTimeout
。但是ko提供了一种定义绑定(bind)顺序的方法,只需查看ko value
的源代码即可绑定(bind),它被定义为'after': ['options', 'foreach']
- 第三,您的 select2 不响应外部更改。例如,如果您有另一个 UI 需要更新
$root.selectedItem
(正常的选择列表),该 UI 引发的更改不会同步回您的 select2。
解决方案
定义select2
基于现有 value
绑定(bind) 绑定(bind)(刚刚发现不需要),并挂接所有更改事件。
- 我们不需要
"select2-removed"
事件,都是关于"change"
事件。 -
select2
提供所有图纸,我们不需要update
回调。 - 使用标志
shouldIgnore
打破值订阅者和 select2 更改事件处理程序之间的循环。
<罢工> http://jsfiddle.net/huocp/8N3zX/6/ 罢工> http://jsfiddle.net/huocp/8N3zX/9/
ko.bindingHandlers.valueSelect2 = {
'after': ['options'],
'init': function(element, valueAccessor, allBindings) {
// kind of extend value binding
// ko.bindingHandlers.value.init(element, valueAccessor, allBindings);
var options = allBindings.get('select2Options') || {};
$(element).select2(options);
var value = valueAccessor();
// init val
$(element).val(ko.unwrap(value)).trigger("change");
var changeListener;
if (ko.isObservable(value)) {
var shouldIgnore = false;
changeListener = value.subscribe(function(newVal) {
if (! shouldIgnore) {
shouldIgnore = true;
// this is just select2 syntax
$(element).val(newVal).trigger("change");
shouldIgnore = false;
}
});
// this demo only works on single select.
$(element).on("change", function(e) {
if (! shouldIgnore) {
shouldIgnore = true;
if (e.val == '') {
// select2 use empty string for unselected value
// it could cause problem when you really want '' as a valid option
value(undefined);
} else {
value(e.val);
}
shouldIgnore = false;
}
});
}
ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
if (changeListener) changeListener.dispose();
$(element).select2("destory");
});
}
};
关于javascript - Select2allowclear和knockout.js,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24712462/