IGNIS
IGNIS

Reputation: 450

Computed vs Observes on Controller in Ember

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

Answers (2)

IGNIS
IGNIS

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

Kingpin2k
Kingpin2k

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

Related Questions