我认为这一定是一种常见的情况,我想知道在 Knockout 中是否有一个公认的惯例来处理这个问题。你有一个“是-否”下拉菜单(或一对单选按钮),它的默认值是一个空白项目(或两个都未选中,对于单选按钮)。用户必须做出选择才能继续。
这并不能完美地映射到您模型中的 bool 值,因为实际上存在三个可能的值。 True、False 和没有用户选择。在 C# 中,您可能会考虑使用 nullable bool 值,在 Java 中你可以使用 java.lang.Boolean .在这两种情况下,“null”都可以表示没有用户选择。
JavaScript 没有可空值,但由于它不强制变量类型,您可以采用特定变量可以为 null、true 或 false 的约定,并以类似于 C# 中可空 bool 值的方式使用它或 java.lang.Boolean。
首先,存在绑定(bind)到 bool 值的问题。 Knockout 希望所有的绑定(bind)值默认都是字符串类型。这是讨论here和 here ,而 RP Niemeyer 提供的解决方案是使用自定义绑定(bind),如下所示:( Link to JS Fiddle for this example )
ko.bindingHandlers.booleanValue = {
init: function(element, valueAccessor, allBindingsAccessor) {
var observable = valueAccessor(),
interceptor = ko.computed({
read: function() {
return observable().toString();
},
write: function(newValue) {
observable(newValue === "true");
}
});
ko.applyBindingsToNode(element, { value: interceptor });
}
};
所以我以此为出发点,想出了这个自定义绑定(bind)。它似乎工作。我对社区对此方法的反馈很感兴趣。查看jsfiddle for this自己试验一下。这有什么缺点和/或可扩展性问题吗?
ko.bindingHandlers.nullableBooleanValue = {
init: function(element, valueAccessor, allBindingsAccessor) {
var observable = valueAccessor(),
interceptor = ko.computed({
read: function() {
console.log(observable());
console.log(typeof(observable()));
var result = null;
if(observable() === true){
result = "true";
} else if(observable() === false){
result = "false";
} else { // Default is null, which represents no user selection
result = "null";
}
console.log("transforming on read:")
console.log(typeof(observable()));
console.log(observable());
console.log(typeof(result));
console.log(result);
return result;
},
write: function(newValue) {
var result = null;
if(newValue === "true"){
result = true;
} else if(newValue === "false"){
result = false;
} else { // Default is null, which represents no user selection
result = null;
}
console.log("transforming on write:")
console.log(typeof(newValue));
console.log(newValue);
console.log(typeof(result));
console.log(result);
observable(result);
}
});
ko.applyBindingsToNode(element, { value: interceptor });
}
};
var model = {
state: ko.observable(null)
};
ko.applyBindings(model);
最佳答案
好吧,扩展器方法并没有按照我想要的方式工作,所以我放弃了它(仍在编辑历史中,如果你好奇的话)。我修改了您的绑定(bind)以将选项放在上面,这样您就不会在 HTML 中指定它们。您还可以选择指定“Null”选项文本(您可以扩展它以允许设置每个标签)。
此方法可让您将可观察对象视为标准的可空 bool 值。这是 HTML(注意,nullLabel
是完全可选的):
<select data-bind="yesNoNull: answer, nullLabel: 'Null' "></select>
<pre data-bind="text: ko.toJSON($root, null, 2)"></pre>
这是绑定(bind):
ko.bindingHandlers.yesNoNull = {
init: function(element, valueAccessor, allBindingsAccessor) {
var target = valueAccessor();
var nullLabel = allBindingsAccessor().nullLabel || "";
var options = function() { return [ nullLabel, "Yes", "No"]; };
ko.bindingHandlers.options.update(element, options, allBindingsAccessor);
var observable = valueAccessor(),
interceptor = ko.computed({
read: function() {
var result = nullLabel;
if(observable() === true){
result = "Yes";
} else if(observable() === false){
result = "No";
}
return result;
},
write: function(newValue) {
var result = null;
if(newValue === "Yes"){
result = true;
} else if(newValue === "No"){
result = false;
}
observable(result);
}
});
ko.applyBindingsToNode(element, { value: interceptor });
}
};
这里是 the fiddle .
关于knockout.js - 是否有一个公认的约定来处理用户输入之前为 "yes-no"的 "unset"下拉菜单?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13293341/