Cascading select lists with KnockoutJS
HTML
<script src="https://dl.dropbox.com/u/6378864/countries.js"></script>
<script src="http://knockoutjs.com/downloads/knockout-2.2.1.js"></script>
<p>Region:
<select data-bind="options: regions, optionsText: 'Name', optionsValue: 'ID', value: selectedRegion"></select>
</p>
<p data-bind="visible: selectedRegion">Country:
<select data-bind="options: countries, optionsText: 'Name', optionsValue: 'ID', value: selectedCountry"></select>
</p>
<p data-bind="visible: hasCity">City:
<select data-bind="options: cities, optionsText: 'Name', optionsValue: 'ID', value: selectedCity"></select>
</p>
JavaScript
(function ($, ko, newData) {
// объявляем нашу viewModel
var ViewModel = function () {
this.selectedRegion = ko.observable();
this.selectedCountry = ko.observable();
this.selectedCity = ko.observable();
this.hasCity = ko.observable(false);
// как только список выше поменялся, дропаем выбранные значения
this.selectedRegion.subscribe(function () {
this.selectedCountry(undefined);
}, this);
this.selectedCountry.subscribe(function () {
this.selectedCity(undefined);
}, this);
this.regions = asyncComputed(function () {
return fakeDataProvider('regions');
}, this);
this.countries = asyncComputed(function () {
return fakeDataProvider('countries', this.selectedRegion());
}, this);
this.cities = asyncComputed(function () {
return fakeDataProvider('cities', this.selectedRegion(), this.selectedCountry());
}, this);
this.cities.subscribe(function () {
this.hasCity(this.cities().length !== 0);
}, this);
};
var model = new ViewModel();
ko.applyBindings(model);
// сервисный код
// Обертка для работы с jQuery реализацией deferred объектов
// подробнее можно почитать в доках
// http://api.jquery.com/category/deferred-object/
// https://github.com/knockout/knockout/wiki/asynchronous-dependent-observables#dependent-observables-that-return-deferred-results
function asyncComputed(evaluator, owner) {
var result = ko.observable();
ko.computed(function() {
evaluator.call(owner).done(result);
});
return result;
}
// просто так... потому что я так хочу
function cleanUpList(list) {
return list.map(function (item) {
return {
ID: item.ID,
Name: item.Name
};
});
}
// утилитка для поиска по...