我在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;
答案 0 :(得分:1)
我不熟悉jQuery.chosen插件,但我可能有一个修复。
我认为<select>
元素有两种显示其值的方法:
value
属性option
绑定selected
属性(通常表示初始选择)。我注意到淘汰赛没有设置selected
属性。当我尝试插件能够在selected
存在的情况下正确设置初始选择时,结果证明它是。
现在,挑战是在最初选择的选项中包含selected
属性。我认为init
方法最适合这种方法,但事实证明默认绑定不会创建选项元素,直到update
... It even deletes any elements that are already there。
所以,最终,我把逻辑放在update
绑定中,一切似乎按预期工作。
请注意,您可能不想进行进一步的测试。此外,我相信你需要返回原始绑定的返回值,因为这可以让淘汰赛知道后代绑定得到了解决。此外,您可能需要查看custom disposal logic以确保从DOM中删除选择后,您的jQuery窗口小部件将被销毁。
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;