2012-03-30 9 views
41

¿Hay alguna manera de asignar un objeto de datos JSON a una matriz observable y luego hacer que cada elemento de la matriz observable se inicialice en un tipo específico de modelo de vista?Asignar datos JSON a Knockout observable Array con vista específica tipo de modelo

He visto toda la documentación de knockout junto con los ejemplos de eliminación y mapeo aquí y no puedo encontrar ninguna respuesta que funcione para lo que busco.

Por lo tanto, tengo los siguientes datos JSON:

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

Y tengo los siguientes modelos de vista:

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(); 
} 

¿Es posible, con la estructura de datos dada y usando el plugin de mapeo de nocaut, para que el StateViewModel resultante contenga un observableArray poblado con 2 CityViewModels, y cada CityViewModel que contiene un observableArray se llene con 2 StreetViewModels?

Utilizando actualmente el plugin de mapeo, puedo hacer que se asigne a un StateViewModel, pero las colecciones de "ciudades" y "calles" se llenan con objetos genéricos en lugar de instancias de mis modelos de vista de ciudad y calle.

Terminan con las propiedades y valores observables correctos en ellos, simplemente no son instancias de mis modelos de vista, que es lo que estoy buscando.

Respuesta

68

Marque esta 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

que tenía un seguimiento pregunta, sin embargo: al crear 'cities', parece que el mapeo' create' realidad devuelve un único objeto de tipo 'CityViewModel', y se pasa un objeto de la ciudad ¿Qué harías si quisieras tener un tipo de colección como 'CitiesViewModel' con sus propios métodos de recopilación? –

+0

Se ve genial? Pero, ¿qué hace el 'this. $ Type = '..Modelo' en los constructores? No puedo encontrar nada sobre una propiedad '$ type' en la documentación en línea Knockout o Knockout.mapping. – Bart

+0

$ type no es realmente necesario ... solo para demostrar que se llamó al constructor. – Artem

Cuestiones relacionadas