knockout.js - привязка данных вложенного массива и каскадных предварительно заполненных выпадающих списков
Я довольно новичок в knockout.js, однако, я с радостью использовал его в своем проекте ASP.NET MVC 4, пока не столкнулся с этим препятствием, которое беспокоило меня какое-то время, кажется, не могу поставить палец на это.
Сценарий, над которым я работаю, требует нескольких комбинаций данных о местоположении (регион, страна, город), то есть каскадных выпадающих списков, что не является проблемой при вводе свежих данных, но я столкнулся с проблемой (ями) при попытке редактировать сохраненные данные.
Данные в формате JSON с вложенными массивами выглядят следующим образом (сокращено в целях иллюстрации):
var newData =
[
{
"ID":1,
"Name":"Australia and New Zealand",
"Countries":[
{
"ID":13,
"Name":"Australia",
"Cities":[
{
"ID":19,
"Name":"Brisbane"
},
{
"ID":28,
"Name":"Cairns"
},
...
Я подозреваю, что не могу загрузить данные (или,привязывать это) правильно, поскольку у меня возникают проблемы с доступом к подмассиву Region (который содержит страны региона) и подмассиву стран (который содержит города стран).
Тогда есть вопрос наличия предварительно заполненных опций, который работает частично, viewmodel загружает количество строк, но ничего не выбирает.
Вот виртуальная машина:
var existingRows = [
{
"Region": 1,
"Country": 13,
"City": 19
},
{
"Region": 1,
"Country": 158,
"City": 3
}];
var Location = function (region, country, city) {
var self = this;
self.region = ko.observable(region);
self.country = ko.observable(country);
self.city = ko.observable(city);
// Whenever the region changes, reset the country selection
self.region.subscribe(function () {
self.country(undefined);
});
// Whenever the country changes, reset the city selection
self.country.subscribe(function () {
self.city(undefined);
});
};
var LocationViewModel = function (data) {
var self = this;
self.lines = ko.observableArray(ko.utils.arrayMap(data, function (row)
{
var rowRegion = ko.utils.arrayFirst(newData, function (region)
{
return region.ID == row.Region;
});
var rowCountry = ko.utils.arrayFirst(rowRegion.Countries, function (country) {
return country.ID == row.Country;
});
var rowCity = ko.utils.arrayFirst(rowCountry.Cities, function (city) {
return city.ID == row.City;
});
return new Location(rowRegion, rowCountry, rowCity);
}));
// Operations
self.addLine = function () {
self.lines.push(new Location())
};
self.removeLine = function (line) {
self.lines.remove(line)
};
};
var lvm = new LocationViewModel(existingRows);
$(function () {
ko.applyBindings(lvm);
});
HTML код:
<tbody data-bind="foreach: lines">
<tr>
<td><select data-bind="options: newData, optionsText: 'Name', optionsValue: 'ID', optionsCaption: 'Select a region...', attr: { name: 'SubRegionIndex' + '['+$index()+']' }, value: region"></select></td>
<td><select data-bind="options: Countries, optionsText: 'Name', optionsValue: 'ID', optionsCaption: 'Select a country...', attr: { name: 'CountryIndex' + '['+$index()+']' }, value: country"></select></td>
<td><select data-bind="options: Cities, optionsText: 'Name', optionsValue: 'ID', optionsCaption: 'Select a city...', attr: { name: 'CityIndex' + '['+$index()+']' }, value: city"></select></td>
<td><a href='#' data-bind='click: $parent.removeLine'>Remove</a></td>
</tr>
</tbody>
Я пытался изменить пример редактора Cart с веб-сайта knockout.js, предварительно заполнив его данными, но не добился большого прогресса, похоже, что-то упустил. На самом деле ничего не нашлось с вложенными массивами, так что я застрял здесь ...
Я поместил полный код на JSFiddle здесь:http://jsfiddle.net/fgXA2/1/
Любая помощь будет оценена.