javascript - Select2allowclear和knockout.js

标签 javascript jquery knockout.js

我使用 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/

相关文章:

javascript - 在 InfoBubble.js 中使用 fancyBox 和 Google Maps API

select - 选择列表初始化时 knockout 触发更改事件

java - 在 Java 中使用 Javascript cookie

javascript - 为什么我的 d3 map 函数返回未定义的源属性?

javascript - 我们如何过渡到同一条路线?

knockout.js - 将参数传递给knockoutjs viewmodel中的函数

javascript - Knockoutjs 跟踪 ajax 调用后的变化

javascript - Google Chrome 中的 Knockout.js 输入类型日期数据绑定(bind)

javascript - Foreach 元素悬停不同的背景

javascript - td 元素内的 100% 高度 div