Сопоставьте данные JSON с Knockout observableArray с конкретным типом модели представления - PullRequest
41 голосов
/ 31 марта 2012

Есть ли способ сопоставить объект данных JSON с наблюдаемым массивом, а затем поочередно инициализировать каждый элемент наблюдаемого массива в модель представления определенного типа?

Я посмотрел вседокументации по нокауту, а также примеров нокаута и сопоставления здесь, и я не могу найти ответ, который подходит для того, что мне нужно.

Итак, у меня есть следующие данные JSON:

    var data = {
    state : {
        name : 'SD',
        cities : [{
            name : 'Sioux Falls',
            streets : [{
                number : 1
            }, {
                number : 3
            }]
        }, {
            name : 'Rapid City',
            streets : [{
                number : 2
            }, {
                number : 4
            }]
        }]
    }
};

И у меня есть следующие модели представлений:

var StateViewModel = function(){
    this.name = ko.observable();
    this.cities = ko.observableArray([new CityViewModel()]);
}

var CityViewModel = function(){
    this.name = ko.observable();
    this.streets = ko.observableArray([new StreetViewModel()]);
}

var StreetViewModel = function(){
    this.number = ko.observable();
}

Возможно ли при заданной структуре данных и с помощью подключаемого модуля отображения нокаута результирующий StateViewModel содержать observableArray, заполненный 2 объектами CityViewModel и каждым объектом CityViewModelсодержащий observableArray, заполненный 2 StreetViewModels?

В настоящее время с помощью подключаемого модуля сопоставления я могу отобразить его на StateViewModel, но коллекции городов и улиц заполняются общими объектами, а не экземплярами.моих моделей с видом на город и улицу.

Они заканчивают соНаправьте наблюдаемые свойства и значения на них, они просто не являются экземплярами моих моделей представлений, и это то, что мне нужно.

1 Ответ

69 голосов
/ 31 марта 2012

Проверьте это http://jsfiddle.net/pTEbA/268/

Object.prototype.getName = function() { 
   var funcNameRegex = /function (.{1,})\(/;
   var results = (funcNameRegex).exec((this).constructor.toString());
   return (results && results.length > 1) ? results[1] : "";
};

function StateViewModel(data){
    this.name = ko.observable();
    ko.mapping.fromJS(data, mapping, this);
}

function CityViewModel(data) {
    this.name = ko.observable();
    ko.mapping.fromJS(data, mapping, this);
}

function StreetViewModel(data) {
    this.name = ko.observable();
    ko.mapping.fromJS(data, mapping, this);
}

var mapping = {
    'cities': {
        create: function(options) {
            return new CityViewModel(options.data);
        }
    },
    'streets': {
        create: function(options) {
            return new StreetViewModel(options.data);
        }
    }
}


var data = { state: {name:'SD', cities:[{name:'Sioux Falls',streets:[{number:1},{number:3}]},
                                        {name:'Rapid City',streets:[{number:2},{number:4}]}]}};

var vm = new StateViewModel(data.state)
console.log(vm);
console.log(vm.getName());
console.log(vm.cities());
console.log(vm.cities()[0].getName());
console.log(vm.cities()[0].streets());
console.log(vm.cities()[0].streets()[0].getName());
​
...