Simple starting point for Ember.js fiddles

HTML

<script src="http://mike.aski.free.fr/js/ember.js"></script>
<script src="http://mike.aski.free.fr/js/ember-data.js"></script>
<script type="text/x-handlebars" data-template-name="posts-view">
    <i>Adding or updating post was detected (red background here), but removing was not detected...</i>
    <b>Fixed!</b>

    {{view Ember.CollectionView contentBinding="posts" itemViewClass="App.PostView"}}
    <button {{action "addPost"}}>Add post</button>
</script>

<script type="text/x-handlebars" data-template-name="post-view">
    <p>
        {{content.title}}
        <button {{action "updatePost"}}>Update post</button>
        <button {{action "deletePost"}}>Delete post</button>
    </p>
</script>

<script type="text/x-handlebars">
    {{view App.PostsView}}
</script>

CSS

.is-dirty {
    background-color: rgba(255, 0, 0, 0.3);
}

.is-deleted {
    display: none;
}

JavaScript

App = Ember.Application.create({});

App.Post = DS.Model.extend({
    title: DS.attr('string')
});

App.Post.FIXTURES = [
    { title: 'My first post' },
    { title: 'Another post' },
    { title: 'Yet another post' }
];

App.store = DS.Store.create({
  revision: 4,
  adapter: DS.fixtureAdapter
});

App.postsController = Ember.ArrayController.create({
    content: App.store.findAll(App.Post)
});

App.PostsView = Ember.View.extend({
    templateName: 'posts-view',
    classNameBindings: ['isDirty'],
    
    postsBinding: 'App.postsController.content',
    originalItemsCount: null,
    feedOriginalItemsCount: function() {
        this.set('originalItemsCount', this.getPath('posts.length'));
    }.observes('posts'),

    isDirty: function() {
        var originalItemsCount = this.get('originalItemsCount');
        var remainingItemsCount = this.get('posts').reduce(function(value, item) {
            if (!(item.get('isNew') || item.get('isDeleted'))) {
                value++;
            }
            return value;
        }, 0);
        var hasDirty = this.get('posts').some(function(post) {
            return post.get('isDirty');
        });
        return hasDirty || (originalItemsCount !== remainingItemsCount);
    }.property('[email protected]'),

    addPost: function() {
        post = App.store.createRecord(App.Post, { title: 'New post' });
    }
});

App.PostView = Ember.View.extend({
    templateName: 'post-view',
    isVisibleBinding: 'notDeleted',
    
    notDeleted: function() {
        return !this.getPath('content.isDeleted');
    }.property('content.isDeleted').cacheable(),

    updatePost: function() {
        this.get('content').set('title', 'New post title...');
    },
    
    deletePost: function() {
        var post = this.get('content');
        post.deleteRecord();
    }
});