Valer
Valer

Reputation: 875

Ember data model reload causes item in {{each}} to be removed/inserted back - losing current state

How could I prevent the itemView from being removed and re-rendered back in place when iterating over a controller's arrangedContent, if the observed model's property doesn't change value?

Short version below, using a blog post App.Post as example model:

Controller:

sortProperties: ['createdAt']

Template:

{{each arrangedContent}}
    {{title}}
    {{body}}
{{/each}}

objectAt(0).reload() causes the corresponding item to be removed and inserted back in the same place. The problem is that the itemView loses the previous state, so the result is some bad user interaction.

I've traced it to this sequence of calls:

1. retrieved record is pushed onto the store
2. notifyPropertyChange('data') onto the record
3. propertyWillChange('createdAt')
4. arrayWillChange() -> this causes the removal of the item, even though
                        the value of createdAt didn't change
5. arrayDidChange()  -> reinserts the object, it gets re-rendered in the list

I'd need it to not to do the remove/insert sequence when the property hasn't changed actual value.

One thought was to queue the removes/inserts in arrayWillChange/arrayDidChange and not call them if the value didn't change. I suspect that this would cause additional sync problems.

Upvotes: 3

Views: 189

Answers (1)

Kingpin2k
Kingpin2k

Reputation: 47367

You're probably using find or all for your collection which makes it a live filter (which removes/adds it to collections on demand. You can move the collection to a plain array, which will take away this logic. You can do this from the route, or controller

Route

App.FooRoute = Em.Route.extend({
  model: function(){
    return this.store.find('foo').then(function(foos){
      return foos.toArray();
    });
  }
});

Controller

App.FooController = Em.ArrayController.extend({
  simpleModel: function(){
    return this.get('model').toArray();
  }.property()
});

Then in your template

{{#each item in simpleModel}}

{{/each}}

Note: when you do this, if you add a new item to the store, you will need to manually add it to the collection.

Upvotes: 1

Related Questions