Knockout.js版本3.4.0打破了jQuery Chosen插件绑定

时间:2016-06-28 05:28:15

标签: knockout.js jquery-plugins jquery-chosen

我在Durandal项目工作,这意味着我使用淘汰库。另外,我使用了jQuery选择的插件。

最近,我将淘汰版从2.0版升级到3.4.0版。作为副作用,选择的插件有缺陷。它有一个错误:第一个选择始终是列表中的第一个项目,无论ko observable的实际值如何。

这是一个复制品:



ko.bindingHandlers.chosen = {
  init: function (element) {
    ko.bindingHandlers.options.init(element);          
    $(element).chosen({ disable_search_threshold: 10 });
  },
  update: function (element, valueAccessor, allBindings) {
    ko.bindingHandlers.options.update(element, valueAccessor, allBindings);
    $(element).trigger('chosen:updated');
  }
};

ko.applyBindings({ 
  getItemAvailableAccessTypes: function(data) {
    return [
      {codeForChosen: "Open", AccessTypeName: "Open access"},
      {codeForChosen: "Restricted", AccessTypeName: "No access"}
    ];
  },
	child: {
    AccessType: ko.observable("Restricted")
  }
});

.chosen-container { width: 100% !important; }
pre { background: white; padding: 10px; color: #333; font: 11px consolas; border: 1px solid #ddd; }

<link href="https://cdnjs.cloudflare.com/ajax/libs/chosen/1.5.1/chosen.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chosen/1.5.1/chosen.jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-debug.js"></script>

<div data-bind="with: child">
<select data-bind="chosen: $parent.getItemAvailableAccessTypes($data), value: $data.AccessType,  optionsText: 'AccessTypeName',  optionsValue: 'codeForChosen'"></select>
</div>
<hr>Debug info: <pre data-bind="text: ko.toJSON($root, null, 2)"></pre>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:1)

我不熟悉jQuery.chosen插件,但我可能有一个修复。

我认为<select>元素有两种显示其值的方法:

  1. 它位于select元素本身的value属性
  2. 并且可以option绑定selected属性(通常表示初始选择)。
  3. 我注意到淘汰赛没有设置selected属性。当我尝试插件能够在selected存在的情况下正确设置初始选择时,结果证明它是。

    现在,挑战是在最初选择的选项中包含selected属性。我认为init方法最适合这种方法,但事实证明默认绑定不会创建选项元素,直到update ... It even deletes any elements that are already there

    所以,最终,我把逻辑放在update绑定中,一切似乎按预期工作。

    请注意,您可能不想进行进一步的测试。此外,我相信你需要返回原始绑定的返回值,因为这可以让淘汰赛知道后代绑定得到了解决。此外,您可能需要查看custom disposal logic以确保从DOM中删除选择后,您的jQuery窗口小部件将被销毁。

    &#13;
    &#13;
    ko.bindingHandlers.chosen = {
      init: function(element) {
        var optionsReturnValue = ko.bindingHandlers.options.init(element);
    
        $(element).chosen({
          disable_search_threshold: 10
        });
    
        return optionsReturnValue;
      },
      update: function(element, valueAccessor, allBindings) {
        ko.bindingHandlers.options.update(element, valueAccessor, allBindings);
    
        var currentValue = ko.unwrap(allBindings.get("value"));
        var selectedOption = element.querySelector("[value=" + currentValue + "]");
        if (selectedOption) {
          selectedOption.setAttribute("selected", "selected");
        }
        
        $(element).trigger('chosen:updated');
      }
    };
    
    ko.applyBindings({
      getItemAvailableAccessTypes: function(data) {
        return [{
          codeForChosen: "Open",
          AccessTypeName: "Open access"
        }, {
          codeForChosen: "Restricted",
          AccessTypeName: "No access"
        }];
      },
      child: {
        AccessType: ko.observable("Restricted")
      }
    });
    &#13;
    .chosen-container {
      width: 100% !important;
    }
    pre {
      background: white;
      padding: 10px;
      color: #333;
      font: 11px consolas;
      border: 1px solid #ddd;
    }
    &#13;
    <link href="https://cdnjs.cloudflare.com/ajax/libs/chosen/1.5.1/chosen.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/chosen/1.5.1/chosen.jquery.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-debug.js"></script>
    
    <div data-bind="with: child">
      <select data-bind="chosen: $parent.getItemAvailableAccessTypes($data), value: $data.AccessType,  optionsText: 'AccessTypeName',  optionsValue: 'codeForChosen'"></select>
    </div>
    <hr>Debug info: <pre data-bind="text: ko.toJSON($root, null, 2)"></pre>
    &#13;
    &#13;
    &#13;