Computed property: detect changes in dynamic object keys

Let’s say I have the following:

expandedStates: null,

init() {
  this._super(...arguments);
  // dynamic shape e.g. { isExpanded__1: true, isExpanded__2: false, ...etc }
  this.set('expandedStates', {});
}

expand: function(id) {
  const key = `isExpanded__${id}`;
  this.set(`expandedStates.${key}`, true);
}

collapse: function(id) {
  const key = `isExpanded__${id}`;
  this.set(`expandedStates.${key}`, false);
}

// can you make this recompute? 
allExpanded: computed('expandedStates', function() {

});

How can you recompute when keys are added to/removed from expandedStates and when the keys themselves are changing? (like from true to false and vice versa)

I was hoping there’d be something like

// this doesn't work but it'd be convenient if it did
allExpanded: computed('expandedStates.{*}', function() {

});

You can do either…

allExpanded: computed('expandedStates.{isExpanded__1,isExpanded__2,isExpanded__3}', function() {

});

or …

expand: function(id) {
  const key = `isExpanded__${key}`;
  this.set('expandedStates', {
    ...this.expandedStates,
    [`expandedStates.${key}`]: true
  });
}
1 Like

The second option works for my use case! Replacing the entire object instead of updating the keys will trigger a recompute. Makes sense, thanks @wuarmin!

1 Like

@orangesoundsnice One thing to note is that with autotracking, this becomes much easier! For instance, the tracked-built-ins library provides a tracked POJO: https://github.com/pzuraq/tracked-built-ins

Using tracked POJOs automatically tracks based on their usage. So, if you loop over all of the keys of the object, it will entangle the entire object. If any keys are added, removed, or updated, then it will recompute:

expandedStates = tracked({});

allExpanded() {
  for (let key in this.expandedStates) {
    // ...
  }
}