Ember.js ArrayProxy Array of Models
ember.js, model
Solution
I took the approach mentioned by Tom Dale which overwrites the `replace` method. It also registers an observer for the `content` property to assure that the content is a typed version of the array, see http://jsfiddle.net/pangratz666/XCLmE/:
App.ModelArrayProxy = Ember.ArrayProxy.extend({
modelType: Ember.required,
_typedArray: function(objects) {
var modelType = this.get('modelType');
var array = objects.map(function(item) {
// check if item is an instance of type
if (!(item instanceof modelType)) {
// create a new instance of type and pass the hash
return modelType.create(item);
}
// just return the item, since it's already of type modelType
return item;
});
return array;
},
contentChanged: function() {
if (!this.get('setTypedContent')) {
var content = this.get('content');
this.set('setTypedContent', true);
this.set('content', this._typedArray(content));
this.set('setTypedContent', false);
}
}.observes('content'),
replace: function(idx, amt, objects) {
this._super(idx, amt, this._typedArray(objects));
}
});
This ModelArrayProxy can then be used as a "normal" `ArrayProxy`:
// model declaration
App.AddressModel = Ember.Object.extend({
...
});
// create a proxy for given modelType
App.proxy = App.ModelArrayProxy.create({
content: [],
modelType: App.AddressModel
});
var myArray = [{
address_name: 'address_name 1',
address: 'address 1'},
{
address_name: 'address_name 2',
address: 'address 2'}];
// set content with "normal" objects
App.proxy.set('content', myArray);
// invoke 'log' on all items in array
App.proxy.forEach(function(item) {
item.log();
});
// push a normal object
App.proxy.pushObject({
address_name: 'address_name 3',
address: 'address 3'
});
// push an instance of App.AddressModel
App.proxy.pushObject(App.AddressModel.create({
address_name: 'address_name 4',
address: 'address 4'
}));
// invoke 'log' on all items in array
App.proxy.forEach(function(item) {
item.log();
});
Problem
Goal To create an array of Model’s, managed by an ArrayController (ArrayProxy). Requirements Use ArrayController (ArrayProxy) abstraction to encapsulate the array of Model’s Convert objects input to ArrayProxy automagically upon insertion into the ArrayProxy Do not lazy convert at access time Example Data Structures ``` App.AddressModel = Ember.Object.extend({ address_name: null, address: null, printme: function() { console.log("Just making sure the array turned into an AddressModel"); }, }); App.addressArray = Ember.ArrayProxy.create({ transformFrom: function(item) { }, transformTo: function(item) { }, arrayContentWillChange: function(startIdx, removeAmt, addAmt) { }, }); ``` Failures by Trial dynamic property Someone in the IRC channel mentioned trying dynamic properties. This resulted in a, what appeared to be by logic and empirical evidence, a recursive result. No doubt from making content both the dynamically generated variable and the ‘trigger/exported’ variable. arrayContentWillChange Again, a seemingly recursive result. Upon receiving a arrayContentWillChange notification I generate an AddressModel from the given array index item(s). I then set the old indexed item to the created Model and an arrayContentWillChange event is triggered again, repeat … recurse. transformFrom / transformTo https://github.com/emberjs/ember.js/pull/554#issuecomment-5401112 tomdale mentions in the above post to try using transformFrom and transformTo to cast the incoming and/or outgoing data. These function don’t seem to exist [http://cloud.github.com/downloads/emberjs/ember.js/ember-0.9.8.js]. ArrayProxy model patch https://github.com/emberjs/ember.js/pull/554 tomdale’s suggestion to the original solution/post to this problem seems to generalize better than the model implementation introduced by jedwood, however, in Backbone.js handles this problem by using the special model variable and I found it to work well. The Question How do I extend ArrayProxy to convert all incoming object, to be managed, into an AddressModel?