Upgrading app from ember 1.7.1 to 1.11.3, data from beta 11 to beta16.1, saving parent of hasMany invalidates all children, even if no children were added/removed/modified


#1

Been working on upgrading an app from EAK 1.7.1 to ember-cli 1.11.3, and ember-data from beta11 to beta16.1, and while it’s been an enormous two week ordeal, I’ve finally gotten the app ported over (ember-cli is such a huge improvement over EAK btw, great work!)

However, I’ve got one remaining issue, and I just can’t seem to figure out how to fix it. I have a view in my app that displays a parent model, along with it’s children, using each child in model.children. On this page, you can edit data fields on the parent, or on the children, but you cannot add or remove children.

The strange thing is in the new version of ember/data, for some reason, whenever I save the parent, it appears to be invalidating the entire child_ids array. This results in the entire each child in model.children block being completely re-rendered (the child views have new ember IDs), and thus any state / in progress editing on the children is lost.

This doesn’t make any sense to me, as no children were added or removed (or even modified), and thus the child_ids should remain the same. Furthermore, this appears to be a total regression on the old behavior, which handled it correctly.

Here’s 2 jsbins to make my issue clearer:

ember 1.7.1 (old, correct behavior): http://jsfiddle.net/kjhangiani/osjcmhop/4/

ember 1.11.3 (new, incorrect behavior) http://jsfiddle.net/kjhangiani/x1zx43pz/

On both of these, first click “parent 1” to load the parent model, with the 3 child models rendered below it. Click on any or all children to expand them. Now, click “click here to save” to simulate saving the parent model - you’ll notice on the old version of ember, the children are correctly left alone and not re-rendered (as they haven’t changed). However, on the new version, all the expanded children will collapse, and in fact inspecting the elements in firebug will show that the ember-ids are changed, as the whole block is being re-rendered.

Furthermore, while in my app there is no way to add or remove children from this page, you can simulate this behavior as well - if you modify the $.mockajx({} block on the jsbin, and set the response to be child_ids:[1, 3] instead - on the old version, this behaves absolutely as expected - child 1 and child 3 are left alone (whether in their expanded or unexpanded state), and child 2 is removed.

On the new version, again, the entire block is being redrawn.

Am I doing something wrong here? I feel like logically this is a regression, though I’m sure there’s a reason for the change. Anyone have any suggestions for a workaround? I’ve tried using components, views, render, and partials for the children, but all of them exhibit the same issue - the problem is with the parent.child_ids property forcing the entire each block to redraw rather than only added, removed, or modified entries.

Any suggestions for how to proceed / workaround this?

*edit: updated old version jsfiddle to work in chrome


#2

I wasn’t able to get your old jsbin working, but from your stated behavior this does seem like a regression. For a temporary workaround that is complex, a bit confusing, and going away in 2.0 you may be able to use http://emberjs.com/api/#method_arrayComputed.

Have you experimented to see if the the issue could be in ember-data as opposed to ember. I wonder if they change the way they rebuild the relationship.


#3

I do indeed think the problem is in ember-data, but I’ve only just started diving through the source code there to see if I can track the problem, so I’ve not really made any headway there.

The jsbin does seem to have an issue in chrome, but it works in firefox for me. The problem is actually one of the external references - embedded-mixin.js from ember-data-extensions, which is what I was using on my older app. I just use a github raw reference to include this file in jsbin and chrome seems to dislike that.

I updated the jsbin and just copy/pasted this mixin into the source. Scroll down past it for the regular code:

http://jsfiddle.net/kjhangiani/osjcmhop/4/

The mixin is the minified version, but the github repo is here:

I think the problem may actually be in EmbeddedMixin vs EmbeddedRecordsMixin, so I’ll start my investigation there, but hopefully that jsbin works for you so you can see the issue.

arrayComputed is actually what I was going to try - feels like such a hack though… my thinking was that I’d copy the children (or preferably, just the child_ids) to an unbound var, and then I can iterate over that var to render the children. I will try actually referencing the children by loading them on the page directly via ID, rather than in an each loop, to see if the problem is indeed the each child in model.children array, or if the problem extends further and is also reloading the children unnecessissarily.

Any assistance would be greatly appreciated, wondering if anyone else has encountered this issue. Surely any situation in which you are working with hasMany children and a parent on the same page would run into this… I don’t feel like the logic/structure I used here is crazy off the rails or anything, and I’m pretty stumped on how to proceed.


#4

Still experiencing this issue, if anyone has any ideas. I need a way to display the parent, as well as the children on the same page, with the children having their own state, and everything editable. If there are workarounds for how to set this up, please let me know.

Thanks!


#5

If the main issues is that you lose state on the redraw you could wrap your EmberData model in your own model that has the extra view state info or if you don’t mind a total hack you could add your view state info the ember data model itself.