renathy
renathy

Reputation: 5355

define knockout logic for dependant arrays for dropdowns

I am having WebApi that returns Countries with Companies.

The object returned is in the following format:

[{"$id":"1", "Name":"Denmark", "Currency":"DKK", "Companies":[],",
{"$id":"2","Name":"Belgium","Currency":"EUR","Companies":[],

{"$id":"3","Name":"Austria","Currency":"EUR","Companies":[{"$id":"4","Name":"Belgium Company 1"},...]

So, there is a list of Countries and each Country has a list of companies.

How to map this structure to knockout?

I have knockout model viewModel with different properties:

 this.objectId = ko.observable();
 this.Country = ko.observable(); // this is selected country for given object
 this.Countries = ko.observableArray();
 this.Company = ko.observable(); //this is selected company for given object
 this.Companies = ko.observableArray();
 this.ContactName = ko.observable();
 ...

When page loads I am populating viewModel and binding UI. During this I also call webApi and get countries+companies in the format as described above.

    function _getCountries() {
    return $.ajax({
        url: "/api/portfolio/GetCountries",
        contentType: "application/json",
        dataType: "json",
        type: "GET"
    });
}

I am calling _getCountries during model initialization that loads model data like objectId, ContactName etc. When this init is done, I am calling _getCountries:

 _getCountries().done(function (dataJson) {
        ko.mapping.fromJS(dataJson, {}, ParentModel.ChildModelInst.Countries);
    }).fail(function () {
        alert("fail");
    });

this.Countries and this.Companies should be used to populate dropdowns, for example:

<select data-bind="options: Countries, value: Country"></select>                    

The question/problem: 1) Above doens't work, because Countries consists of objects and it shows me dropdown with "objects"

2) I need somehow define Countries and Companies so that those are related. If I change countries then appropriate companies are loaded into dropdown. (so this.Companies should be loaded accordingly to this.Country that is selected item from this.Countries).

Upvotes: 1

Views: 90

Answers (1)

DevelopmentIsMyPassion
DevelopmentIsMyPassion

Reputation: 3591

You need to created computed observable to get company names. So i suggest following.

Html for Country and Company dropdown

<select data-bind="options: Countries, value: Country, optionsText: 'Name'"></select>

<select data-bind="options: filteredCompanies, optionsText: 'Name'"></select>

On subscribe event of "Country" created computed function to return list of Companies for the selected Countries

this.Country.subscribe(function(value) {

      self.filteredCompanies = ko.computed(function() {

          if (value.Companies != undefined){
              return value.Companies;

          }

        });

 });

Upvotes: 1

Related Questions