Cascading Select Menu Knockout.js

by marrok

HTML

<table>
    <tr>
        <td>Country</td>
        <td>
            <select 
                data-bind="options: countries, optionsText: 'countryName', value: selectedCountry, optionsCaption: 'Choose...'">
            </select>
        </td>
    </tr>
    <tr data-bind="visible: selectedCountry">
        <td>State</td>
        <td>
            <select 
                data-bind="options: selectedStates, optionsText: 'stateName', optionsValue: 'stateName', value: selectedState, optionsCaption: 'Choose...'">
            </select>
        </td>
    </tr>
</table>

JavaScript

var country = function (countryId, countryName) {
    this.countryId = ko.observable(countryId); 
    this.countryName = ko.observable(countryName);
};
var state = function (stateId, stateName, countryId) {
    this.stateId = ko.observable(stateId);
    this.stateName = ko.observable(stateName);
    this.countryId = ko.observable(countryId);
};

var viewModel = {
    countries: ko.observableArray([
                new country(1, "USA"),
                new country(2, "Germany"),
                new country(3, "India")
            ]),
    selectedCountry: ko.observable(), // Nothing selected by default

    states: ko.observableArray([
                new state(101, "California", 1),
                new state(201, "Berlin", 2),
                new state(301, "Kerala", 3)
            ]),
    selectedState: ko.observable()// Nothing selected by default
};

viewModel.selectedStates = ko.computed(function () {
    var country = this.selectedCountry(), countryId;
    if (country) {
        countryId = country.countryId();
          return ko.utils.arrayFilter(this.states(), function(state) {
            return state.countryId() === countryId;        
        });
    }
    
    return [];
}, viewModel);

ko.applyBindings(viewModel);