Dynamic ComputedProperty dependencies


#1
Ember.Object.create({

    if_A_then_B_else_C: function(){

        if(this.get('A')){
          return this.get('B');
        }else{
          return this.get('C');
        }

    }.property('A', 'B', 'C')
});

If ‘A’ resolves to true, ‘C’ should be removed from the dependency list of the property.

This was briefly mentioned in this year’s JSConf talk by Marious Gundersen.


#2

If B won’t be ever be false then you can do something like this. If it can, the same general idea will work, you just need some more code to check. The if_A_then_B_else_C should not invalidate unless the value of if_A_then_B or C change.

Ember.Object.create({
    if_A_then_B_else_C: function(){
        return this.get('if_A_then_B') || this.get('C');
    }.property('if_A_then_B', 'C'),
    if_A_then_B: function(){
        if (this.get('A')){
          return this.get('B');
        }
    }.property('A', 'B')
});

Frankly, though, I would go with the most readable solution unless you have an measurable performance impact.


#3

If computed properties kept track of which properties were accessed during their execution, it would be possible for Ember to automatically add these properties as dependencies without any annotations at all. Example:

Ember.Object.create({
    X: function() {
        return this.get('A') ? this.get('B') : this.get('C');
    }.property()
});

Suppose the first time get('X') is called A == true. Then A and B will be accessed within the CP and dynamically added to the dependencies, but C will not. If C changes nothing happens, if A or B change then X will be invalidated and its dependencies cleared. Repeat the process on subsequent get's.

I think it’s a cool idea but I suspect things could get tricky for more complex properties like @each and [].

It would be very challenging to track get's in this way though. For instance, this.get('a.b') could also be accessed as this.get('a').get('b'). So @michaelb’s suggestion is a great compromise: specify all the dependencies up front, but try to remove unused dependencies when possible.