2012-03-30 145 views
41

有没有办法将JSON数据对象映射到可观察数组,然后将每个可观察数组的对象初始化为特定类型的视图模型?将JSON数据映射到具有特定视图模型类型的Knockout observableArray

我已经看过所有的基诺的文档以及淘汰赛和映射的例子在这里,我找不到任何答案适用于我后。

所以,我有以下的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包含一个使用2个CityViewModel填充的observableArray,并且每个CityViewModel包含一个使用2个StreetViewModel填充的observableArray?

目前使用映射插件,我能得到它映射到StateViewModel,但“城市”和“街道”集合填充通用对象,而不是我的城市和街景模型的实例。

他们最终得到了正确的可观察属性和值,他们只是我的视图模型的实例,这就是我所追求的。

回答

68

入住这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()); 
​ 
+1

我也有一个,虽然跟进的问题:创建'cities'时,它看起来像'create'映射实际上返回类型CityViewModel'的'一个对象,并传递一个城市对象。如果您想拥有像“CitiesViewModel”这样的集合类型以及其自己的收集方法,您会做什么? – 2014-11-12 12:02:51

+0

看起来不错?但是这个。$ type ='..Model'在构造函数中做了什么?我无法在在线Knockout或Knockout.mapping文档中找到有关'$ type'属性的任何信息。 – Bart 2014-12-04 12:49:15

+0

$ type实际上并不是必要的......只是为了演示构造函数被调用。 – Artem 2014-12-04 13:29:01