1
votes

Ember CLI + Ember 2.1

I have a child component that is observing a key/value hash on a parent component that keeps track of "required" objects.

requiredObjects: {
  object1_id: true,
  object2_id: false,
  ...
}

These objects are records retrieved from Ember-Data. Whether or not an object is required is a transient property relevant only to the component, which is why I don't use a 'required' property on the object itself.

There are several child components that display one or more of these objects using different data visualizations, and each of these has yet another child component with controls for requiring the object.

The control itself sends actions up to the parent controller, and receives the requiredList from the parent controller. What I'd like to do is this...

isRequired: Ember.computed('player', `requiredList.${this.get('player.id')}`, {
    get(key) {
        return this.get(`requiredList.${this.get('player.id')}`);
    }, 
    set(key, value) {
        this.set(`requiredList.${this.get('player.id')}`, value);
        return value;
    }
}),

However, that doesn't work. Essentially, I need to observe when a key in requiredList that matches player.id is updated, but I don't know the id until the component is initialized and 'player' is set. Is there a way to do this?

I thought about using an array instead of a key/value hash, but that requires every control to loop over the array each time membership changes and see whether its player is in the requiredList. That seems pretty inefficient, given that there are usually a couple hundred players in the list, each with 2 or 3 controls currently rendered in different parts of the page.

Update

So moving it into init() fixes the problem, though I have no idea why.

init() {
    this._super(...arguments);
    this.set('isRequired', Ember.computed('player', `requiredList.${this.get('player.id')}`, {
        get(key) {
            return this.get(`requiredList.${this.get('player.id')}`);
        }, 
        set(key, value) {
            this.set(`requiredList.${this.get('player.id')}`, value);
            return value;
        }
    }));
},
1

1 Answers

0
votes

The templated string evaluates with the current context.

In the first case, the context is actually the module itself, which by the spec is undefined, so requiredList.${this.get('player.id')} => requiredList.undefined.

In the second case you're inside the init() function, so this is the object.