Knockout.js boolean data-binding issues with radio buttons

booleandata-bindingknockout.jsobservable

I'm currently doing the following to compensate for boolean's not mapping well to radio buttons. I am stuck binding 1 and 0 to the value (instead of true and false) because of how the fields are read out of the observables. The value of Pref1/Pref2 come as true/false boolean values from the server. The key here is I want to not only data-bind the checked value of the radio button to match the true/false in the object, but I also want the boolean value of true/false to be written back into the GraduationClass object. My compensation code is not only ugly, but not scalable.

<input type="radio" value="1" name="radioGroup" data-bind="checked: Pref1" />Yes
<input type="radio" value="0" name="radioGroup" data-bind="checked: Pref2" />No    
<a href="javascript:void(0);" data-bind="click: $root.saveGraduationClass ">Save</a>  

function SiteSettingsViewModel() {
    var self = this;
    this.saveGraduationClass = function(graduationClass) {
        // hack until i get a custom radio button binding
        if (graduationClass.Pref1() == 1) {
            graduationClass.Pref1(true);            
        } else {
            graduationClass.Pref1(false);            
        }  

        if (graduationClass.Pref2() == 1) {
            graduationClass.Pref2(true);
        } else {
            graduationClass.Pref2(false);
        }

        // ...ajax call to save graduationClass to the server
    }

function GraduationClass(data) {
    var self = this;
    ko.mapping.fromJS(data, {}, this);
}

Best Answer

Here is example from knockoutJs website, that demonstrate how to use radio buttons with "checked" attribute:

<p>Send me spam: <input type="checkbox" data-bind="checked: wantsSpam" /></p>
<div data-bind="visible: wantsSpam">
    Preferred flavor of spam:
    <div><input type="radio" name="flavorGroup" value="cherry" data-bind="checked: spamFlavor" /> Cherry</div>
    <div><input type="radio" name="flavorGroup" value="almond" data-bind="checked: spamFlavor" /> Almond</div>
    <div><input type="radio" name="flavorGroup" value="msg" data-bind="checked: spamFlavor" /> Monosodium Glutamate</div>
</div>

<script type="text/javascript">
    var viewModel = {
        wantsSpam: ko.observable(true),
        spamFlavor: ko.observable("almond") // Initially selects only the Almond radio button
    };

    // ... then later ...
    viewModel.spamFlavor("msg"); // Now only Monosodium Glutamate is checked
</script>

But I dont understand why you use two objects - "Pref1" and "Pref2" fro one radiobutton group "radioGroup"? In this case you just could use one object as in an example used "spamFlavor".

So, please, describe more ditaily what you want to bind: one radiobuttons group by one selected value, or something else.

Also you could use computed observables to calculate different values, please see example.