user1496062
user1496062

Reputation: 1317

knockoutjs binding dependent selectlist

Ok i have quite a large amount hierarchical data .

I foreach over 1 part

I then have a drop down list which works

<p  data-bind="visible: Id">
  Race:
  <select data-bind="options: $parent.data.Races, optionsText: 'Name' , optionsValue:        'Id',     value: RaceId, optionsCaption: 'Choose...'"></select>
</p> 

But binding using the raceId to lookup the valid genders does not work as the context does not change with the with binding.

<p data-bind="with: $parent.data.Races()[ RaceId ]">
    <pre data-bind="text: ko.toJSON($data,null , 2) "></pre> //debug

    Gender:
    <select data-bind="options: Genders, optionsText: 'Name' , optionsValue: 'Id', value:  $parent.Gender, optionsCaption: 'Choose...'"></select>
</p>

Note its the with that fails to change the context , everything is observable .

I have thought of doing this with a function but that is a bit tricky as well since it needs to change when raceId changes ( and when raceId is not set either be hidden or an empty list)

Any help would be appreciated.

Here is my current function attempt ( and yes im new to javascript) , though the with binding would be far more elegant.

self.getGenderForRace = ko.computed( function () {
    if ( this && this.data) {
        return this.data.Races()[this.RaceId].Genders;
    } else {
        return new Array();
    }

    deferEvaluation: true;
}, this);

This is some of my view model

l6.CreateViewModel = function (options) {
var self = this;


//this.getGenderForRace = ko.computed(function (character) {
//    return this.data.Races()[character.RaceId].Genders;
//}, this);

self.getGenderForRace = ko.computed( function () {
    if ( this && this.data) {
        return this.data.Races()[this.RaceId].Genders;
    } else {
        return new Array();
    }

    deferEvaluation: true;
}, this);

self.setData = function (url, raceId, factionId, viewmodel) {



    $.getJSON(url, { raceId: raceId, factionId: factionId }, function (data) {
        viewmodel.data = ko.mapping.fromJS(data.Data);

        ko.applyBindings(viewmodel);  // we dont bind till we get data
        // add to strcture and map!
        //self.data = data.Data; 
        $("#tabContainer").tabs();

    });

Upvotes: 0

Views: 1814

Answers (3)

Zholen
Zholen

Reputation: 1790

If you have broken up data like I do in my project where depending on each selection you have to make an ajax call here's an example of how you can do that.

http://jsfiddle.net/Zholen/h7j3f/

Upvotes: 1

John Earles
John Earles

Reputation: 7194

Here is a working fiddle that demonstrates a way to do what you are looking for: http://jsfiddle.net/jearles/Q8kcs/

Is there any reason you are messing with the Ids? With a select the value binding can save the entire selected observable. That allows us easy access to the available sub options.

Upvotes: 0

mhu
mhu

Reputation: 18041

If you want to include deferEvaluation: true, you should pass it as an option to ko.computed:

self.getGenderForRace = ko.computed({
    read: function() {
        if ( this && this.data) {
            return this.data.Races()[this.RaceId].Genders;
        } else {
            return [];
        }
    },
    deferEvaluation: true
}, this);

Upvotes: 0

Related Questions