与布尔值绑定的淘汰赛单选按钮
Knockout radio button binding with boolean
根据我在 运行 时创建的 Fiddle 它没有按预期将值绑定到 "no Blue" 选项。
var viewModel = {
isBlue: ko.observable(false)
//isBlue: ko.observable("false") this works
};
正如我在其中提到的,当我传递一个字符串值 "false" 时,它会进行绑定。很明显,knockout 也进行了类型比较。
在我的应用程序中,我使用创建视图模型的 komapper。对于 boolean 中的属性,它创建 bool 值并初始化 bool 中的变量。
我需要将它们转换为字符串吗?在输入单选按钮元素中,我们将始终使用字符串值。我可以为复选框使用布尔值吗?
我试过 "checkedValue" 还是不行。
是的。 src
内部绑定只是 returns element.value
,对于浏览器来说是一个 字符串 。检查 the source file,使用此 abbreviated/annotated 代码获取与被检查相关的值:
var checkedValue = ko.pureComputed(function() {
// Abbreviated, first KO does some stuff for other cases, but
// in the end it'll do:
return element.value; // Where `element` is the actual DOM element.
});
通常情况下,布尔值将由一个复选框表示,您只会在一半的情况下遇到问题(在这些情况下您需要类似“an inverse checked binding”的内容)。
解决方案包括您提到的那个(使用字符串)以及使用可写的计算前端实际可观察的,例如:
viewModel.viewIsBlue = ko.computed({
read: function() { return viewModel.isBlue().toLocaleString(); },
write: function(newVal) { viewModel.isBlue(newVal === 'true'); }
});
如果您发现自己过于频繁地重复上述操作,您也可以使用具有类似功能的自定义扩展器。
我 认为 您遇到了一个错误,该错误已在更高版本的 Knockout 中得到修复。
它的工作方式(就像您尝试过的那样):
<input name="Test" type="radio" data-bind="checkedValue: true,
checked: isBlue" />Blue
<input name="Test" type="radio" data-bind="checkedValue: false,
checked: isBlue" />No Blue
ko.applyBindings({
isBlue: ko.observable(false)
});
如果包含淘汰版 3.4,它会按预期工作:
ko.applyBindings({
isBlue: ko.observable(false)
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>
<label>
<input name="Test" type="radio" data-bind="checkedValue: true, checked: isBlue" /> Blue
</label>
<label>
<input name="Test" type="radio" data-bind="checkedValue: false, checked: isBlue" /> No Blue
</label>
<br />
<strong style="color: green">3.4.0: Does work</strong>
当您包含您在 fiddle (2.1.0) 中使用的版本时,它不会:
ko.applyBindings({
isBlue: ko.observable(false)
});
<script src="https://cloud.github.com/downloads/knockout/knockout/knockout-2.1.0.js"></script>
<label>
<input name="Test" type="radio" data-bind="checkedValue: true, checked: isBlue" />Blue
</label>
<label>
<input name="Test" type="radio" data-bind="checkedValue: false, checked: isBlue" />No Blue
</label>
<br />
<strong style="color: red">2.1.0: Does not work</strong>
编辑: 经过更多挖掘:我不认为这是 2.1.0 中的错误; checkedValue
那时甚至不存在!
查看源代码,您会注意到获取检查值的逻辑在 2.1.0 和更高版本之间有很大不同:
在 2.1.0 中:
if (element.type == "checkbox") {
valueToWrite = element.checked;
} else if ((element.type == "radio") && (element.checked)) {
valueToWrite = element.value;
}
在 3.4.0 中:
var checkedValue = ko.pureComputed(function() {
// Treat "value" like "checkedValue" when it is included with "checked" binding
if (allBindings['has']('checkedValue')) {
return ko.utils.unwrapObservable(allBindings.get('checkedValue'));
} else if (allBindings['has']('value')) {
return ko.utils.unwrapObservable(allBindings.get('value'));
}
return element.value;
});
所以一个明确的答案是:更新到 3.4.0,或者创建一个实现 3.4.0 行为的自定义检查绑定(如果版本更新会破坏您的项目)
根据我在 运行 时创建的 Fiddle 它没有按预期将值绑定到 "no Blue" 选项。
var viewModel = {
isBlue: ko.observable(false)
//isBlue: ko.observable("false") this works
};
正如我在其中提到的,当我传递一个字符串值 "false" 时,它会进行绑定。很明显,knockout 也进行了类型比较。
在我的应用程序中,我使用创建视图模型的 komapper。对于 boolean 中的属性,它创建 bool 值并初始化 bool 中的变量。 我需要将它们转换为字符串吗?在输入单选按钮元素中,我们将始终使用字符串值。我可以为复选框使用布尔值吗?
我试过 "checkedValue" 还是不行。
是的。 src
内部绑定只是 returns element.value
,对于浏览器来说是一个 字符串 。检查 the source file,使用此 abbreviated/annotated 代码获取与被检查相关的值:
var checkedValue = ko.pureComputed(function() {
// Abbreviated, first KO does some stuff for other cases, but
// in the end it'll do:
return element.value; // Where `element` is the actual DOM element.
});
通常情况下,布尔值将由一个复选框表示,您只会在一半的情况下遇到问题(在这些情况下您需要类似“an inverse checked binding”的内容)。
解决方案包括您提到的那个(使用字符串)以及使用可写的计算前端实际可观察的,例如:
viewModel.viewIsBlue = ko.computed({
read: function() { return viewModel.isBlue().toLocaleString(); },
write: function(newVal) { viewModel.isBlue(newVal === 'true'); }
});
如果您发现自己过于频繁地重复上述操作,您也可以使用具有类似功能的自定义扩展器。
我 认为 您遇到了一个错误,该错误已在更高版本的 Knockout 中得到修复。
它的工作方式(就像您尝试过的那样):
<input name="Test" type="radio" data-bind="checkedValue: true,
checked: isBlue" />Blue
<input name="Test" type="radio" data-bind="checkedValue: false,
checked: isBlue" />No Blue
ko.applyBindings({
isBlue: ko.observable(false)
});
如果包含淘汰版 3.4,它会按预期工作:
ko.applyBindings({
isBlue: ko.observable(false)
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>
<label>
<input name="Test" type="radio" data-bind="checkedValue: true, checked: isBlue" /> Blue
</label>
<label>
<input name="Test" type="radio" data-bind="checkedValue: false, checked: isBlue" /> No Blue
</label>
<br />
<strong style="color: green">3.4.0: Does work</strong>
当您包含您在 fiddle (2.1.0) 中使用的版本时,它不会:
ko.applyBindings({
isBlue: ko.observable(false)
});
<script src="https://cloud.github.com/downloads/knockout/knockout/knockout-2.1.0.js"></script>
<label>
<input name="Test" type="radio" data-bind="checkedValue: true, checked: isBlue" />Blue
</label>
<label>
<input name="Test" type="radio" data-bind="checkedValue: false, checked: isBlue" />No Blue
</label>
<br />
<strong style="color: red">2.1.0: Does not work</strong>
编辑: 经过更多挖掘:我不认为这是 2.1.0 中的错误; checkedValue
那时甚至不存在!
查看源代码,您会注意到获取检查值的逻辑在 2.1.0 和更高版本之间有很大不同:
在 2.1.0 中:
if (element.type == "checkbox") {
valueToWrite = element.checked;
} else if ((element.type == "radio") && (element.checked)) {
valueToWrite = element.value;
}
在 3.4.0 中:
var checkedValue = ko.pureComputed(function() {
// Treat "value" like "checkedValue" when it is included with "checked" binding
if (allBindings['has']('checkedValue')) {
return ko.utils.unwrapObservable(allBindings.get('checkedValue'));
} else if (allBindings['has']('value')) {
return ko.utils.unwrapObservable(allBindings.get('value'));
}
return element.value;
});
所以一个明确的答案是:更新到 3.4.0,或者创建一个实现 3.4.0 行为的自定义检查绑定(如果版本更新会破坏您的项目)