Is there such as thing as dynamic computed
properties? I think a bit of code would make more sense.
Let’s say there is an object like this:
const fruitVendor = {
weeks: {
'2018-10-07': {
available: ['apples', 'bananas', 'pears']
},
...
},
...
}
The data will always be in this format: fruitVendor.weeks.<YYYY-MM-DD>.available
.
There could be a lot weeks
, but I may only care about a computed property on this week. Right now I need to do something like this:
myComputedProperty: computed('fruitVendor.weeks', ...)
Whereas, ideally, I had something like this:
myComputedProperty: computed('fruitVendor.weeks.<getThisWeek()>.available', ...)
How do you handle something like this?
You could use another computed with a second dependent key on the week of interest?
@computed('weeks', 'selectedWeek')
get someData() {
return this.weeks[this.selectedWeek];
}
ef4
October 8, 2018, 12:05pm
4
Sometimes in these cases, things get simpler if you replace some of your computed properties with helpers.
1 Like
This is quite easy to do in plain ember once you get your head around it:
Although not built into Ember, there is a straightforward approach to defining computed properties that have dynamic, or computed, dependent keys.
There’s also an addon but I haven’t tried it:
1 Like
Thanks @alexspeller . While I didn’t do it exactly like in the linked article, I used defineProperty
in init
so it is something like this:
init() {
this._super(...arguments);
const currentWeek = this.get('week');
defineProperty(this, '_availableCurrentWeek', computed.oneWay(`fruitVendor.weeks.${currentWeek}.available`));
},
I would suggest not using “defineProperty”.
In docs you can find sentence:
“NOTE: This is a low-level method used by other parts of the API. You almost never want to call this method directly.”
But you cen easily set property
init() {
this._super(...arguments);
const currentWeek = this.get('week');
set(this, '_availableCurrentWeek', computed.oneWay(`fruitVendor.weeks.${currentWeek}.available`));
},
1 Like
The use of either defineProperty
or set
a computed
was removed. This example no longer works.
Since I already resurrected this thread I should at least followup with a nifty solution to my dilemma regarding dynamic dependencies. I was inspired by the link given by @alexspeller above.
I had a need to have a POJO passed into a component and then have the component glean dependencies from the object’s keys.
state: reads('stateManager.state'),
isAllSelected: equal('state', STATES.ALL),
isNoneSelected: equal('state', STATES.NONE),
isSomeSelected: equal('state', STATES.SOME),
stateManager: computed('selected', function() {
let properties = Object.keys(this.selected);
return EmberObject.extend({
properties,
state: computed(`selected.{${properties.join(',')}}`, function() {
let selections = Object.values(this.selected);
if (selections.every(x => x)) {
return STATES.ALL;
} else if (selections.every(x => !x)) {
return STATES.NONE;
} else {
return STATES.SOME;
}
})
}).create({ selected: this.selected });
}),
The caveat is that this will not detect new keys or deleted keys but in my case this was fine as the selected
POJO would never change like that. I needed only to track the values of those keys but the keys were not known until the component was initialized. This works for that use case.