Question

I have my view model:

function (dataservice, Person){
    var genders = ko.observableArray();
    var languages = ko.observableArray();
    var person = ko.observableArray();

    function activate(){
        dataservice.getGenders(genders);
        dataservice.getGenders(languages);
    }

    var vm = {
        genders: genders,
        languages: languages,
        person: person
    };
}

function Person(person){
    var firtstName = person.firtstName;
    var familyName = person.familyName;
    var genderId = person.genderId;
    var languageId = person.languageId;
}

It's simplified for clarity.

Then I have my `Genders' data from server, it looks like this:

[{
    $id: "1",
    GenderId: 2,
    GenderName: "Female",
    GenderDescription: "Female",
    GenderCode: "F"
}]

I also have Languages that looks like this:

[{
    "$id": "1",
    "LanguageId": 2,
    "LanguageName": "Afar",
    "LanguageDescription": "Afar",
    "LanguageCode": "aa"
}]

What I am trying to achieve is to bind the genders array from my view model as a data source and use Person.GenderId as the value to be updated, in a way such that the correct radio button is initially selected. This selection depended on Person.GenderId.

I did something similar with Languages using a drop down and that works just fine:

<section data-bind="with: $root.personModel">
   <select id="language" 
           data-bind="options: $root.languages, 
                      optionsText: 'LanguageName', 
                      optionsValue: 'LanguageId',
                      value: LanguageId, 
                      optionsCaption: 'none'">
    </select>
</section>

Now I am trying to do the same thing with radio buttons, but I don't know how to make it work. Here's what I have:

<section data-bind="with: $root.personModel">
   <!-- ko foreach: $root.genders -->
   <input type="radio" 
          name="genders" 
          data-bind="attr: {value: GenderId}, checked: GenderId" />
   <span data-bind="text: $data.GenderName"></span>
   <!-- /ko -->
</section>

If I understood things correctly, the foreach binding works like with and changes my context, so I can't reach GenderId from my exposed Person.

Was it helpful?

Solution

change

<input type="radio" name="genders" data-bind="attr: {value: GenderId}, checked: GenderId" />

to

<input type="radio" name="genders" data-bind="attr: {value: GenderId}, checked: $parent.GenderId" />

as explained here

$parent: This is the view model object in the parent context, the one immeditely outside the current context. In the root context, this is undefined.

OTHER TIPS

You will need to utilize the checkdValue binding, see the lower part of the "checked" documentation.

Your code didn't quite translate to a repro, but here's my version more or less in your scenario. Suppose this bit of code:

var Person = function(person) {
    var self = this;
    self.name = ko.observable(person.name);
    self.gender = ko.observable(person.gender);
};

var root = {
    genders: [{ $id: "1", GenderId: 1, GenderName: "Female"},
              { $id: "2", GenderId: 2, GenderName: "Male"}]
};

root.personModel = new Person({name: 'john', gender: root.genders[1]});

ko.applyBindings(root);

Alongside this markup:

<section data-bind="with: $root.personModel">
    <!-- ko foreach: $root.genders -->
    <input type="radio" 
           name="genders" 
           data-bind="checkedValue: $data, checked: $root.personModel.gender" />
    <span data-bind="text: $data.GenderName"></span><br />
    <!-- /ko -->
</section>

This should work, see this fiddle.

The objects from the genders array are bound to the checkedValue of each input, and the personModel's gender is bound to checked.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top