Improving UI Stability with Ember Data and ArrayProxy

I’ve grown fond of Ember.js over the past two years. In that time it has evolved quite a bit. Recently, HTMLBars and more mature versions of Ember Data have been particularly welcome additions. That forward progress, and varying project needs, mean that I’m still regularly learning more about its quirks, tools, and doing things the “Ember way” (or all three at once). Just a week ago, that was the case while working with Ember Data relationships, an ArrayProxy, and rendering controllers.

It all started when we added a list of items using Ember’s each template helper with an itemController set to provide some additional functionality (and UI state along with it). For the purpose of illustration, consider an application that shows a list of Comments for an Article using a similar scheme.

We found a few undesirable results from this setup:

  • Any time a comment is added to an article, all comments are re-rendered and the user loses any UI state captured in the comment controllers.
  • Comments deleted from the Ember Data store have a tendency to re-appear when adding another comment to the article.
  • A naive sorting implementation also resulted in re-rendering of all comments when a comment was removed.

This jsbin illustrates the way we worked through those problems using Ember’s ArrayProxy–a tool I hadn’t made much use of until now. Before you go digging into the code, though, here are a few notes:

Problem: Ember Data reports that models are added to a relationship’s array even if a model with the same id is already present. This causes re-rendering of controllers unnecessarily.

Solution: Reduce the propagation of changes in an Ember Data relationship’s ManyArray to only the essential changes. An ArrayController is introduced that checks for a model with the same id and only allows the array change to propagate if it is not already present.

Problem: Our naive sorting implementation causes re-rendering when a comment is deleted.

Solution: Introduce another layer of ArrayProxy with Ember’s SortableMixin to handle sorting in a more stable way.

Problem: Ember Data has a bug when dealing with deleted models. They re-appear when a new comment is added to an article.

Solution: Use the ArrayController to also filter out deleted comments before rendering the list.

See the jsbin example for more details.