Select2 allowclear和kickout.js [英] Select2 allowclear and knockout.js
问题描述
我通过以下简单绑定使用select2和淘汰赛:
I use select2 and knockoutJs with this simple binding:
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...
的占位符值.
it works! Now I enabled the allowClear
option in Select2 to clear dropdown to a placeholder value like Select an item...
.
如果我单击x
图标下拉列表,则会正确设置占位符,但删除后不会更新可观察的绑定值!
If I click the x
icon dropdown properly sets the placeholder but knockout don't update observable binded value!
我认为我必须更改自定义绑定,添加以下内容:
I think I've to change custombinding adding something like this:
setTimeout(function () {
$(element).select2(options).on("select2-removed", function (e) {
ko.bindingHandlers.value.update(element, function () { return ''; });
});
...
但是它不起作用!
推荐答案
有几个问题.
1)绑定处理程序中的update
是根据值更改更新DOM ,您永远不要定义具有修改模型能力的update
回调.
1) the update
in bindinghandler is to update DOM based on value change, you should never define an update
callback with the ability to mutate your model.
正确的方法是,在定义新的绑定处理程序时,使用init
回调将所有change
事件与模型挂钩,update
回调仅仅是 DOM绘制例程.
The right way is, when define a new bindinghandler, use init
callback to hook up all change
events with the model, the update
callback is merely a DOM drawing routine.
如果init
提供了DOM绘图(例如select2提供的),则无需定义update
回调.
If your init
provided DOM drawing (such as provided by select2), you don't need to define an update
callback.
因此,ko.bindingHandlers.value.update(element, function () { return ''; });
行仅重绘了DOM,它没有执行您想要的操作.
Hence the line ko.bindingHandlers.value.update(element, function () { return ''; });
only redraw the DOM, it doesn't do what you want.
2)您创建的select2
绑定有一些漏洞.
2) the select2
binding you created has some holes.
- 首先,
value
绑定不知道select2
绑定的存在,这就是您要努力的地方. - 第二秒,您的
select2
绑定必须等待其他绑定(options
绑定)才能完成DOM创建,这就是为什么使用setTimeout
的原因.但是ko提供了一种定义绑定顺序的方法,只需查看ko value
绑定的源代码,它的定义为'after': ['options', 'foreach']
- 第三,您的select2不响应外部更改.例如,如果您有另一个UI更新
$root.selectedItem
(常规选择列表),则该UI引发的更改将不会同步回您的select2.
- first,
value
binding doesn't know the existence ofselect2
binding, that's where you struggled. - second, your
select2
binding has to wait for other binding (theoptions
binding) to finish DOM creation, what's why you usesetTimeout
. But ko provided a way to define sequence of the bindings, just look the source code ofko value
binding, it's defined as'after': ['options', 'foreach']
- third, your select2 doesn't respond to outside change. For instance, if you have another UI to update
$root.selectedItem
(a normal select list), the change raised by that UI would not sync back to your select2.
解决方案
根据现有的value
绑定(只是发现不需要)来定义select2
绑定,并挂接所有更改事件.
Define select2
binding based on existing (just found out it's not needed), and hook up all change events.value
binding
- 我们不需要
"select2-removed"
事件,这全都与"change"
事件有关. -
select2
提供了所有图形,我们不需要update
回调. - 使用标志
shouldIgnore
中断值订户和select2更改事件处理程序之间的循环.
- we don't need
"select2-removed"
event, it's all about"change"
event. select2
provided all drawing, we don't needupdate
callback.- use a flag
shouldIgnore
to break the loop between value subscriber and select2 change event handler.
http://jsfiddle.net/huocp/8N3zX/6/
http://jsfiddle.net/huocp/8N3zX/9/
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");
});
}
};
这篇关于Select2 allowclear和kickout.js的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!