Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HasMany addArrayObserver arrayWillChange/arrayDidChange unexpected behavior #2981

Closed
lsowen opened this issue Apr 8, 2015 · 8 comments
Closed

Comments

@lsowen
Copy link

lsowen commented Apr 8, 2015

I'm trying to use DS.hasMany.addArrayObserver to monitor when new elements are inserted (either created client side or loaded from the server). However, the arguments passed to arrayWillChange and arrayDidChange are weird, in that if I add one record the removeCount is equal to the old HasMany length and the addCount is equal to the new HasMany length.

In other words, it looks like the "array" is emptied and all new records are added. Is this the expected behavior? If so, what is the proper way to get just the records which are being added/removed?

I have set up an example which demonstrates the difference in behavior between an array and a HasMany relationship: http://emberjs.jsbin.com/hozononusu/1/edit?html,js,console,output

@lsowen
Copy link
Author

lsowen commented Apr 9, 2015

Further research seems to yield that it is indeed (currently) the expected behavior, as flushCanonical creates a new array by filtering out deleted elements and appending new elements:

flushCanonical: function() {

So I have two questions:

  1. Is there a good way to listen for new and removed elements from the hasMany array?
  2. A comment in flushCanonical talks about the need for "proper diffing". Has work on this started anywhere? (and how could I help with the need?)

@lsowen
Copy link
Author

lsowen commented Apr 10, 2015

At least as a work around, I was able to using DS.Store.filter() to get the relevant records and call .addArrayObserver on those. More info on my StackOverflow question: http://stackoverflow.com/a/29561953/3108853

@miguelcobain
Copy link

I also ran into this problem. My hasMany relationship looked like it was being "reset", by some reason.
I solved it by using an intermediate computed property to create a new array containing my elements.

  componentMaterials: Ember.computed('model.someHasManyRelationship.[]', function() {
    return DS.PromiseArray.create({
      promise: this.get('model.someHasManyRelationship').then(r => {
        return Ember.A().addObjects(r);
      })
    });
  }),

@Vincz
Copy link

Vincz commented Feb 26, 2016

I'm currently running into the same issue. I do have a big process each time a record is added / deleted to a relationship. With the current behavior, whenever i add something, everything is removed then everything is append again.

@miguelcobain With your solution, i don't even get the notification from the array observer. Did you find something else ?

@BryanCrotaz
Copy link
Contributor

PR #4583 should fix this

@runspired
Copy link
Contributor

it looks like the "array" is emptied and all new records are added

Short answer, yes, this is exactly what is happening. Long answer, it's actually much worse than that but I'm working on refactoring and optimizing that layer. The work from @BryanCrotaz will likely help, but after looking at his approach and the different layers of the onion I suspect a more general array diffing algorithm is what we need but to use one we need to first correct the change flow / triplicated diff that's there right now.

@BryanCrotaz
Copy link
Contributor

@runspired I've refactored out a general array diff in PR #4583

@stefanpenner
Copy link
Member

#4850 was merged, this can be closed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants