将Knockout JS中的单选button绑定到true / false

在我的视图模型中,我有一个值为true或false的IsMale值。

在我的用户界面,我希望将其绑定到以下单选button:

<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> 

我认为checked的问题需要一个string“true”/“false”。 所以我的问题是,我怎么能得到这个双向绑定w /这个用户界面和模型?

一种select是使用可写的计算可观察值 。

在这种情况下,我认为一个很好的select是使可计算可观察值成为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 }); }; 

你可以在你的用户界面中绑定它:

 <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> 

示例: http : //jsfiddle.net/rniemeyer/Pjdse/

我知道这是一个古老的线索,但我遇到了同样的问题,并发现了一个更好的解决scheme,可能在这个问题被正式回答后添加到淘汰赛,所以我会留给那些有同样问题的人。

目前不需要扩展程序,自定义绑定处理程序或计算机。 只要提供一个“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"/> 

要么:

 <input type="radio" name="b" data-bind="checked:Quantity, checkedValue: 1"/> <input type="radio" name="b" data-bind="checked:Quantity, checkedValue: 2"/> <input type="radio" name="b" data-bind="checked:Quantity, checkedValue: 3"/> 

这适用于我:

http://jsfiddle.net/zrBuL/291/

 <label>Male <input type="radio" name="IsMale" value="1" data-bind="checked:IsMale"/> </label> <label>Female <input type="radio" name="IsMale" value="0" data-bind="checked:IsMale"/> </label> 
 ko.bindingHandlers['radiobuttonyesno'] = { 'init': function (element, valueAccessor, allBindingsAccessor) { var stateHandler = function (property, allBindingsAccessor, key, value, checkIfDifferent) { if (!property || !ko.isObservable(property)) { var propWriters = allBindingsAccessor()['_ko_property_writers']; if (propWriters && propWriters[key]) propWriters[key](value); } else if (ko.isWriteableObservable(property) && (!checkIfDifferent || property.peek() !== value)) { property(value); } }; var updateHandler = function () { var valueToWrite; if ((element.type == "radio") && (element.checked)) { valueToWrite = element.value; } else { return; // "radiobuttonyesno" binding only responds to selected radio buttons } valueToWrite = (valueToWrite === "True") ? true : false; var modelValue = valueAccessor(), unwrappedValue = ko.utils.unwrapObservable(modelValue); //can be true of false stateHandler(modelValue, allBindingsAccessor, 'checked', valueToWrite, true); }; ko.utils.registerEventHandler(element, "click", updateHandler); // IE 6 won't allow radio buttons to be selected unless they have a name if ((element.type == "radio") && !element.name) ko.bindingHandlers['uniqueName']['init'](element, function () { return true }); }, 'update': function (element, valueAccessor) { var value = ko.utils.unwrapObservable(valueAccessor()); value = value ? "True" : "False"; if (element.type == "radio") { element.checked = (element.value == value); } } }; 

使用这个联编程序,而不是创build愚蠢的ko计算observables。

例:

 <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> 

一旦你发现单选button的初始匹配只想匹配一个string,并希望将该值设置为一个string, 那么只需要将初始值转换为string即可。 我必须用Int值来对抗。

在你设置完可观察值之后,把这个值转换成string,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> 

在开发过程中,我在网页底部使用了“全部转储到屏幕上”。

 <h4>Debug</h4> <pre data-bind="text: ko.toJSON($data, null, 2)"></pre> 

这里是数据值, 之前

 "OrderStatusID": 6, "ManifestEntered": true, 

之后

 "OrderStatusID": "6", "ManifestEntered": "True", 

在我的项目中,我不需要转换Bools,因为我可以使用不具有相同挫败感的checkbox。

为什么不是简单的真假而不是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> 

你也可以使用扩展器,所以很容易重用它们以获得更多的可观察性:

 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的参数指示该值是否为空。

http://jsfiddle.net/G8qs9/1/

在3.0之前的老版本的淘汰赛做了大量的研究后,可能有两个最好的select

创build一个淘汰赛扩展像

 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> 

来源: http : //www.timlabonne.com/2013/02/building-a-knockout-js-extender-for-boolean-values/