Javascript 将true/false绑定到敲除JS中的单选按钮
在我的视图模型中,我有一个IsMale值,它的值为true或false 在我的UI中,我希望将其绑定到以下单选按钮:Javascript 将true/false绑定到敲除JS中的单选按钮,javascript,knockout.js,knockout-mapping-plugin,knockout-2.0,Javascript,Knockout.js,Knockout Mapping Plugin,Knockout 2.0,在我的视图模型中,我有一个IsMale值,它的值为true或false 在我的UI中,我希望将其绑定到以下单选按钮: <label>Male <input type="radio" name="IsMale" value="true" data-bind="checked:IsMale"/> </label> <label>Female <input type="radio" name="IsMale" value="false
<label>Male
<input type="radio" name="IsMale" value="true" data-bind="checked:IsMale"/>
</label>
<label>Female
<input type="radio" name="IsMale" value="false" data-bind="checked:IsMale"/>
</label>
男性
女性
我认为问题是选中了
需要一个字符串“true”/“false”。因此,我的问题是,我如何获得这种带有此UI和模型的双向绑定?这对我来说很有用:
男性
女性
一个选项是使用
在这种情况下,我认为一个很好的选择是将可写的计算可观测值设置为IsMale
可观测值的“子可观测值”。您的视图模型如下所示:
var ViewModel = function() {
this.IsMale = ko.observable(true);
this.IsMale.ForEditing = ko.computed({
read: function() {
return this.IsMale().toString();
},
write: function(newValue) {
this.IsMale(newValue === "true");
},
owner: this
});
};
您可以将其绑定到UI中,如下所示:
<label>Male
<input type="radio" name="IsMale" value="true" data-bind="checked:IsMale.ForEditing"/>
</label>
<label>Female
<input type="radio" name="IsMale" value="false" data-bind="checked:IsMale.ForEditing"/>
</label>
男性
女性
示例:为什么不简单地选择true和false,而不是1和0
<label>Male
<input type="radio" name="IsMale" value="true" data-bind="checked:IsMale"/>
</label>
<label>Female
<input type="radio" name="IsMale" value="false" data-bind="checked:IsMale"/>
</label>
男性
女性
使用此绑定器,而不是创建可观察的对象
例如:
<label>Male
<input type="radio" name="IsMale" value="True" data-bind="radiobuttonyesno:IsMale"/>
</label>
<label>Female
<input type="radio" name="IsMale" value="False" data-bind="radiobuttonyesno:IsMale"/>
</label>
男性
女性
我知道这是一个老问题,但我也遇到了同样的问题,并且找到了一个更好的解决方案,在这个问题得到正式回答后,这个解决方案可能被添加到knockout中,所以我将把它留给有同样问题的人
目前不需要扩展器、自定义绑定处理程序或Computed。
只需提供一个“checkedValue”选项,它将使用该选项而不是html的“value”属性,并且您可以通过该选项传递任何javascript值
<input type="radio" name="a" data-bind="checked:IsChecked, checkedValue: true"/>
<input type="radio" name="a" data-bind="checked:IsChecked, checkedValue: false"/>
或:
您还可以使用,以便可以轻松地重用它们以获得更多的可观察性:
ko.extenders.boolForEditing = function (target, allowNull) {
var result = ko.computed({
read: function () {
var current = target();
var newValue = null;
if (current === undefined || current === null || current === '') {
if (!allowNull) {
newValue = 'false';
}
} else {
newValue = current ? 'true' : 'false';
}
return newValue;
},
write: function (newValue) {
var current = target();
var valueToWrite = null;
if (newValue === undefined || newValue === null || newValue === '') {
if (!allowNull) {
valueToWrite = false;
}
} else {
valueToWrite = newValue === 'true';
}
// only write if it changed
if (valueToWrite !== current) {
target(valueToWrite);
} else {
if (newValue !== current) {
target.notifySubscribers(valueToWrite);
}
}
}
}).extend({
notify: 'always'
});
result(target());
return result;
};
然后像这样使用它:
this.IsMale.forEditing = this.IsMale.extend({boolForEditing: true});
提供给boolForEditing
的参数指示该值是否可以为null
请参见一旦您发现单选按钮的初始匹配只想匹配字符串,并且想将值设置为字符串,只需将初始值转换为字符串即可。我不得不用Int值来解决这个问题 在你设置好你的观测值之后,把值转换成字符串,KO将从那里开始发挥它的魔力。如果要使用单独的线进行映射,请在这些线中进行转换 在示例代码中,我使用Json在单个命令中映射整个模型。 然后让Razor在转换的引号之间插入值
script type="text/javascript">
KoSetup.ViewModel = ko.mapping.fromJS(@Html.Raw(Json.Encode(Model)));
KoSetup.ViewModel.ManifestEntered("@Model.ManifestEntered"); //Bool
KoSetup.ViewModel.OrderStatusID("@Model.OrderStatusID"); //Int
</script>
在
"OrderStatusID": "6",
"ManifestEntered": "True",
在我的项目中,我不需要转换布尔值,因为我可以使用一个没有同样挫折感的复选框。在对3.0之前的旧版本淘汰进行了大量研究之后,可能有两个最佳选择
创建一个敲除扩展器,如
ko.extenders["booleanValue"] = function (target) {
target.formattedValue = ko.computed({
read: function () {
if (target() === true) return "True";
else if (target() === false) return "False";
},
write: function (newValue) {
if (newValue) {
if (newValue === "False") target(false);
else if (newValue === "True") target(true);
}
}
});
target.formattedValue(target());
return target;
};
要在模型上使用扩展器,请执行以下操作:
function Order() {
this.wantsFries= ko.observable(false).extend({ booleanValue: null });
}
<span>Do you want fries with that?</span>
<label>
<input type="radio" name="question" value="True"
data-bind="value: wantsFries.formattedValue" /> Yes
</label>
<label>
<input type="radio" name="question" value="False"
data-bind="value: wantsFries.formattedValue" /> No
</label>
函数顺序(){
this.wantsFries=ko.observable(false).extend({booleanValue:null});
}
你要炸薯条吗?
对
不
来源:我看到的唯一问题是,当序列化viewmodel以传递给服务器时,您将获得observable中的整数(而不是布尔值)。您需要调用
vm.IsMale(!!vm.+IsMale())
在序列化json以发送到服务器(以防服务器端无法正确处理)之前,我认为您是对的,但我缺乏Javascript知识。你能给我解释一下怎么做吗作品我不熟悉这种语法。@C.J.这会将字符串或数字转换为布尔值-检查这个,如果字符串已经是布尔值,它会将其保留为布尔值。我认为这也是一个很好的解决方案,但并不是双向的。加载时不检查单选按钮。这似乎是一个很好的解决方案。我使用映射插件刷新我的虚拟机。你知道这会消除IsMale上的预言吗?这里有一个替代方案,它将计算出的可观察创建推到自定义绑定中,这将使您不必担心在映射插件:+1中使用绑定来处理它,而不是在每个object@RPNiemeyer绝对是正确的选择。@RPNiemeyer谢谢!注释中的那个小把戏对我来说很有用。如果你发送json对象,它会有所不同。看看源代码,它似乎决定使用选中的值。“useCheckedValue”设置为true。另外,我正在使用淘汰赛3.0。看看这是否有帮助。是的,谢谢,我已经升级到3.0.0,现在它就在那里了。仍然需要将布尔值包装为字符串,因为服务器代码需要这些值;-)好消息。另外两点:(1)我发现,对于v3.0之前的敲除,我可以使用值
绑定,然后使用检查的
绑定(按顺序),但对于3.0,我必须使用检查的值
绑定,而不是值
绑定。(2) pre-v3.0对要求值
绑定先于已检查的
绑定才能正常工作非常挑剔,因此我觉得如果将已检查的
绑定放在已检查的
绑定之前,v3.0在所有情况下都可能工作得更好,就像它们在中所显示的那样。@ZiglioNZ一种可能失败的方法是,如果您的checked
setter(或者可能依赖于它的东西)引发了一个错误,那么正确的复选框没有被选中。我正在使用版本3.4,并且发现我仍然必须输入value=“true”如需了解淘汰版本>=3.0,请参阅比公认答案所建议的更简单的解决方案。
<h4>Debug</h4>
<pre data-bind="text: ko.toJSON($data, null, 2)"></pre>
"OrderStatusID": 6,
"ManifestEntered": true,
"OrderStatusID": "6",
"ManifestEntered": "True",
ko.extenders["booleanValue"] = function (target) {
target.formattedValue = ko.computed({
read: function () {
if (target() === true) return "True";
else if (target() === false) return "False";
},
write: function (newValue) {
if (newValue) {
if (newValue === "False") target(false);
else if (newValue === "True") target(true);
}
}
});
target.formattedValue(target());
return target;
};
function Order() {
this.wantsFries= ko.observable(false).extend({ booleanValue: null });
}
<span>Do you want fries with that?</span>
<label>
<input type="radio" name="question" value="True"
data-bind="value: wantsFries.formattedValue" /> Yes
</label>
<label>
<input type="radio" name="question" value="False"
data-bind="value: wantsFries.formattedValue" /> No
</label>