I have a problem with a setter on a computed property which is an array. It seems like setter is not fired for arrays.
Here is a minimized code just for demonstrating my problem. There is also a JSFiddle: http://jsfiddle.net/NQKvy/970/
App.People = DS.Model.extend({
array1: DS.attr('array', {defaultValue: [{name: 'Hans Maulwurf'},
{name: 'Karl Käfer'}]}),
array2: function(key, value){
var array1 = this.get('array1'),
array2 = [];
if (arguments.length === 2) {
this.set('array1', value);
}
if (array1 === undefined || typeof array1 === null) {
return null;
}
$.each(array1, function(index, value){
array2.pushObject( {name: value.name} );
});
return Ember.isNone(array2) ? null : array2;
}.property('array1.@each')
});
App.IndexRoute = Ember.Route.extend({
model: function(){
return this.store.createRecord('people', {
})
}
});
App.IndexController = Ember.ObjectController.extend({
actions: {
newPerson1: function() {
this.get('model.array1').pushObject({name: 'Klaus Kobold'});
},
newPerson2: function() {
this.get('model.array2').pushObject({name: 'Klaus Mann'});
}
}
});
Everything is fine when I push a person to array1. Computed property is updated properly. But when I push a person to array2 (the computed property) array1 is not updated even so a setter is implemented.
Normally it is no problem to update an property through a computed property (http://emberjs.com/guides/object-model/computed-properties/#toc_setting-computed-properties). But in this case EmberJS doesn't set value when changing the array.
Did I make a mistake or is it really not possible in EmberJS? If so do you have an idea how to achieve this?
I have to change the array through a computed property. There is no other way for my use case.
Update:
As kingpin2k pointed out it's only a problem when not setting a new value for whole array but pushing a new element to an existing array. I updated the JSFiddle to demonstrate the difference: http://jsfiddle.net/NQKvy/972/ As you can see array1 got updated when setting a new value to array2 by changePerson2 action but is not updated when pushing a new element to the array by newPerson2 action.
I figured out that there is a dirty workaround. I could set the computed property again after pushing an element to the array:
this.get('model.array2').pushObject({name: 'Detlef Workaround'});
this.set('model.array2', this.get('model.array2'));
Action dirtyWorkaround in fiddle is demonstrating this. But isn't there another way?
A few word about my use case: I am using computed properties for encryption / decryption of data. The normal property which is send to server is encrypted with Stanford Javascript Crypto Library (SJCL). Decryption / encryption is handled by a computed property. So application access all data through computed properties. This works totally fine for data type String, Date etc. I only run into problems with arrays.
array2, so it wouldn't call the computed property's setter. Please explain why you think you have to change the array through the computed property. - Kingpin2k