Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/440.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 选择2 allowclear和knockout.js_Javascript_Jquery_Knockout.js - Fatal编程技术网

Javascript 选择2 allowclear和knockout.js

Javascript 选择2 allowclear和knockout.js,javascript,jquery,knockout.js,Javascript,Jquery,Knockout.js,我使用select2和knockoutJs进行以下简单绑定: ko.bindingHandlers.select2 = { init: function (element, valueAccessor, allBindings, viewModel, bindingContext) { var options = ko.toJS(valueAccessor()) || {}; setTimeout(function () { $(e

我使用select2和knockoutJs进行以下简单绑定:

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>

但这行不通

有两个问题

1) bindinghandler中的
更新
是基于值更改更新DOM,您永远不应该定义一个能够改变模型的
更新
回调

正确的方法是,在定义新的bindinghandler时,使用
init
callback将所有
change
事件与模型连接起来,
update
回调仅仅是一个DOM绘图例程

如果您的
init
提供了DOM图形(例如由select2提供),则不需要定义
update
回调

因此,行
ko.bindingHandlers.value.update(元素,函数(){return';})仅重新绘制DOM,它不会执行您想要的操作

2) 您创建的
select2
绑定有一些漏洞

  • 首先,
    value
    binding不知道
    select2
    binding的存在,这正是您需要解决的问题
  • 其次,您的
    select2
    绑定必须等待其他绑定(
    选项
    绑定)完成DOM创建,这就是为什么要使用
    setTimeout
    。但是ko提供了一种定义绑定序列的方法,只需查看
    ko value
    绑定的源代码,它被定义为
    'after':['options','foreach']
  • 第三,select2不会对外部变化做出响应。例如,如果您有另一个UI要更新
    $root.selectedItem
    (一个普通的选择列表),该UI引发的更改将不会同步回您的select2
解决方案

根据现有的
值定义
选择2
绑定(刚刚发现不需要),并连接所有更改事件

  • 我们不需要
    “select2 removed”
    事件,这一切都是关于
    “change”
    事件的
  • 选择2
    提供所有绘图,我们不需要
    更新
    回调
  • 使用标志
    shouldIgnore
    中断值订阅服务器和select2更改事件处理程序之间的循环


你能用你的代码提供一个JSFIDLE吗setTimeout有什么用?此外,我只能看到“init”实现,如果您有一个“update”实现,是否也可以在bindingHandler中显示您的“update”实现?要遵循ko实践,changeListener的内容应该转到
valueSelect2.update
callback。
setTimeout(function () {
    $(element).select2(options).on("select2-removed", function (e) {
       ko.bindingHandlers.value.update(element, function () { return ''; });
    });
...
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");
        });
    }
};