Reputation: 450
It was always my understanding that .observes('someProperty')
and .property('someProperty')
worked exactly the same, except that the former is used for triggering function calls and the latter is used to keep object properties up to date.
But now I'm having a problem. My controller code looks like this:
_logChange: function(){
console.log('model array observer fired');
}.observes('model.@each'),
statsData: function(){
console.log('statsData being updated');
...
return someArray;
}.property('model.@each')
The observer and computed property both watch model.@each but for some reason, the observer fires on every model change and the property only updates TWICE before mysteriously going dead. statsData
is calculated once on initial page load, and once on the first route transition, then after that, none of the transitions (with the changes in the underlying model
they make) affect it.
What's going on here? Shouldn't they respond to change in the same way?
Note that I am using the statsData
property in my template.
Upvotes: 2
Views: 1543
Reputation: 450
Thanks to the lovely folks on Ember IRC, I was able to figure it out. The problem was that I was passing statsData
to a component, like this: {{common-statistics values=statsData}}
and in the component, I had this function:
_validateValues: function(){
var values = this.get('values');
if(!values || !Ember.isArray(values) || values.length === 0)
{
this.set('values',[]);
}
}.on('willInsertElement')
which is, as you can see, setting values
if it's not what the component is expecting. Unfortunately, this was affecting statsData
on the controller as well, thanks to this JavaScript language feature. By setting statsData
in the component, I was breaking the computed property on the controller.
So it was never a problem with Ember at all. I just failed to realize that object properties on Ember objects behave the same way they do on "regular JavaScript objects."
Upvotes: 2
Reputation: 47367
observers fire immediately, computed's fire as part of the run loop and scheduled in a debounced fashion. Currently all you're watching is that you add or remove an item to the collection, not whether or not a property on one of the items in the collection has changed. If you want to watch a particular property, you need to specify it.
statsData: function(){
console.log('statsData being updated');
...
return someArray;
}.property('[email protected]')
if you just want to watch the collection changing you should just use []
statsData: function(){
console.log('statsData being updated');
...
return someArray;
}.property('model.[]')
Upvotes: 2