Javascript 将true/false绑定到敲除JS中的单选按钮

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

在我的视图模型中,我有一个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" 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>