Reputation: 18557
I have an ArrayController
which is periodically updated. It has a sorted
computed property which keeps things in order. I'm trying to use a CollectionView
with it's content
property bound to the sorted
property, but it's not rendering them in the correct order. demo
I've obviously made the false assumption that order is maintained between the content
and childViews
property. What is the correct way to do this?
Handlebars:
<script type="text/x-handlebars" data-template-name="item">
id {{view.content.id}}
</script>
<script type="text/x-handlebars">
<ul>
{{collection
contentBinding="App.itemController.sorted"
itemViewClass="App.ItemView"
}}
</ul>
</script>
JavaScript:
App = Ember.Application.create({
ready: function(){
// add a new object with a random id
// every second
setInterval(function(){
var id = Math.round(Math.random() * 100),
obj = Em.Object.create({ id: id });
App.itemController.pushObject(obj);
}, 1000);
}
});
// Collection Item View
App.ItemView = Em.View.extend({
tagName: "li",
templateName: "item"
});
App.itemController = Em.ArrayController.create({
// random order
content: Em.A([
Em.Object.create({ id: 5 }),
Em.Object.create({ id: 3 }),
Em.Object.create({ id: 10 }),
Em.Object.create({ id: 6 }),
Em.Object.create({ id: 1 }),
Em.Object.create({ id: 2 }),
Em.Object.create({ id: 100 }),
]),
// filtered content
sorted: function(){
return this.get('content').sort(function(a,b){
return a.get('id') - b.get('id');
});
}.property("@each")
});
Upvotes: 4
Views: 2600
Reputation: 12011
Inspired by this answer: ember.js #each order by property
I use the sorting properties of ArrayController: https://github.com/emberjs/ember.js/blob/master/packages/ember-runtime/lib/mixins/sortable.js
I don't use CollectionView, but a simple #each, and call to addObject instead of pushObject
template
<script type="text/x-handlebars" data-template-name="item">
id {{view.content.id}}
</script>
<script type="text/x-handlebars" data-template-name="application">
<ul>
{{#each item in App.itemController}}
{{view App.ItemView contentBinding="item"}}
{{/each}}
<li>
</script>
javascript
App = Ember.Application.create({
ready: function() {
// add a new object with a random id
// every second
setInterval(function(){
var id = Math.round(Math.random() * 100),
obj = Em.Object.create({ id: id });
// should call addObject, because pushObject does not sort the inserted item
//App.itemController.pushObject(obj);
App.itemController.addObject(obj);
}, 1000);
}
});
// Collection Item View
App.ItemView = Em.View.extend({
tagName: "li",
templateName: "item"
});
App.itemController = Em.ArrayController.create({
sortProperties: ['id'],
// random order
content: Em.A([
Em.Object.create({ id: 5 }),
Em.Object.create({ id: 3 }),
Em.Object.create({ id: 10 }),
Em.Object.create({ id: 6 }),
Em.Object.create({ id: 1 }),
Em.Object.create({ id: 2 }),
Em.Object.create({ id: 100 }),
]),
});
App.ApplicationView = Ember.View.extend({
templateName: 'application'
});
App.ApplicationController = Ember.Controller.extend();
App.Router = Ember.Router.extend({root: Em.Route.extend()});
App.initialize();
The jsfiddle: http://jsfiddle.net/Sly7/LJAYk/
Upvotes: 5
Reputation: 16163
For the sake of completeness to @sly7_7's correct answer, here is a version with CollectionView
, see http://jsfiddle.net/pangratz666/ctPAA/.
Handlebars:
<script type="text/x-handlebars">
{{collection
tagName="ul"
contentBinding="App.itemController"
itemViewClass="App.ItemView" }}
</script>
JavaScript:
App.itemController = Em.ArrayController.create({
sortProperties: 'id'.w(),
// random order
content: Em.A([
...
])
});
Upvotes: 7