Ember #each rerendering

by Jonesy

HTML

<script src="https://github.com/downloads/emberjs/ember.js/ember-0.9.8.1.js"></script>
<div id="main" role="application">

    <script type="text/x-handlebars">
      {{#with App.todosController}}
        {{#each unfinishedTodos}}
             {{view App.TodoView contentBinding="this"}}
        {{/each}}
        <button {{action "addTodo" target="App.todosController"}}>Add todo</button>
        <hr>
        {{#each finishedTodos}}
             {{view App.TodoView contentBinding="this"}}
        {{/each}}
      {{/with}}
    </script>
    <script type="text/x-handlebars" id="todo">
        {{view Ember.Checkbox checkedBinding="content.finished"}}
        {{content.description}}<br>
    </script>
</div>

JavaScript

/* 

- Ember 0.9.8.1
- When you you have about 50+ items rendering from an ArrayController's computed property, there's a slight delay checking a todo or adding a new todo to the list compared to only 10 or so items.
- From what I can tell, the list rerenders itself when items are removed/added, which I'm sure is the expected behavior, so it could very well be that this is the incorrect use case. In anycase, it does run very slow.

*/
window.CONFIG = {
    totalTodos: 100
};

window.App = Ember.Application.create();

App.Todo = Ember.Object.extend({
    finished: null,
    description: null
});

App.todosController = Ember.ArrayController.create({
    content: [],
    
    finishedTodos: function() {
        return this.filterProperty('finished', true);
    }.property('@each.finished'),
    
    unfinishedTodos: function() {
        return this.filterProperty('finished', false);
    }.property('@each.finished'),
    
    addTodo: function() {
        var content = this.get('content'),
            total = this.get('length'),
            newIndex = ++total;

        content.pushObject(App.Todo.create({
                description: "do something "+ newIndex,
                finished: false
            })
        );    
    },
        
    loadTodos: function() {
        var todos = Ember.A([]);
        for (var i = 0, len = CONFIG.totalTodos; i < len; i++) {
            todos.pushObject(App.Todo.create({
                    description: "do something "+i,
                    finished: false
                })
            );
        }
        this.set('content', todos);
    }
});

App.TodoView = Ember.View.extend({
    templateName: 'todo'
});

App.todosController.loadTodos();