Ember.js: Computed properties on `hasMany` relationships don't update after model saves

Created on 19 Feb 2018  路  5Comments  路  Source: emberjs/ember.js

With Ember 3.0.0 (and also with 3.1.0-beta.1 and canary), but not with Ember <= 2.18.2, filterBy on a hasMany relationship aren't being recomputed when a property changes on one of the underlying models.

Reproduced in a simple new app: https://github.com/pgengler/ember-update-bug.
The app consists of two <ul>s, one displaying "saved" models (isNew=false) and the other displaying "pending" models (isNew=true), and a button that creates a new model and saves it. While it's saving, it should appear in the "Pending" section and once the POST completes (and isNew gets sets to false on the model) it should then appear in the "Saved" section.

With Ember >= 3.0.0, a newly-created thing never moves from "Pending" (with <= 2.18.2 it works as expected). If I do some logging like this:

      let task = this.get('store').createRecord('task', {
        description: 'new task',
        list: this.get('list')
      });
      next(function() {
        task.save()
          .then(() => console.log('task.isNew: %s', task.get('isNew'))
          .then(() => console.log('tasks.mapBy(isNew): %O', list.get('tasks').mapBy('isNew'));
      });

I see that isNew for the new task has changed to false (as expected) but the mapBy returns [true].

Most helpful comment

It's the same issue as https://github.com/emberjs/data/pull/5359

The workaround there is to set up the relationship _after_ calling createRecord

addTask() {
  let task = this.get('store').createRecord('task', {
    description: 'new task',
    // list: this.get('list')
  });
  task.set('list', this.get('list'));
  next(() => task.save());
}

All 5 comments

I was noticing the same thing in Ember 3.0.0 in my models. For example (variables renamed to protect the innocent):

  persistedThings: computed('[email protected]', function() {
    let things = this.get('things').toArray();

    return _.filter(things, function(thing) {
      return thing.get('isNew') === false;
    });
  }),

This code wasn't running after saving a new Thing. It doesn't even run after reloading the parent model (which itself is a hasMany on another model). The code does run when the first createRecord is called and it also gets run when a Thing is deleted. Maybe there's an is equal check that's returning the wrong value on the hasMany arrays when they're updated in the "save" case?

It's the same issue as https://github.com/emberjs/data/pull/5359

The workaround there is to set up the relationship _after_ calling createRecord

addTask() {
  let task = this.get('store').createRecord('task', {
    description: 'new task',
    // list: this.get('list')
  });
  task.set('list', this.get('list'));
  next(() => task.save());
}

Just wanted to comment I'm still seeing this behavior in Ember 3.2.1 / Ember Data 3.1.1.

I believe this is closed (sitting with @runspired )

@stefanpenner Is there a particular commit/release that may have fixed this? I can test with my app and see if it's squashed.

Was this page helpful?
0 / 5 - 0 ratings