[フレーム]
Last Updated: February 25, 2016
·
3.334K
· bashir

Sorted Collections - SortedArrayController in Ember.js

Problem

Need a collection of objects that always render in a sorted order and not the insert order. For example showing events ordered on timestamp.
Update: added maximum size so it will always trim the collection to a running set of n latest items.

Solution

I created this small extension to ember that will keep the collection always sorted (based on a sortFunction or default sort order). It also supports reverse order and random order. The code is in coffeescript but you can convert it to javascript via this tool.

Ember.SortedArrayController = Ember.ArrayController.extend(
 sortOrder: "normal"
 sortFunction: null
 inputCollectionName: "content"
 outputCollectionName: "content"
 maxCollectionSize: -1

 init: ->
 @set(@inputCollectionName, [])
 @addObserver(@inputCollectionName + '.@each', -> @elementAdded())
 @addObserver(@outputCollectionName + '.@each', -> @trimArray())

 elementAdded: (->
 context = @
 content = @get(@inputCollectionName)

 if @sortOrder == "normal"
 if @sortFunction? then content.sort((a,b)-> context.sortFunction(a,b)) else content.sort()
 else if @sortOrder == "reverse"
 if @sortFunction? then content.sort((a,b)-> context.sortFunction(b,a)) else content.reverse()
 else if @sortOrder == "random"
 content.sort((a,b)-> 0.5 - Math.random("deadbeef"))

 @set(@outputCollectionName, content)
 )

 trimArray: (->
 content = @get(@outputCollectionName)
 @set(@outputCollectionName, content.slice(0, @maxCollectionSize-1))if (@maxCollectionSize > 0) and (content.length > @maxCollectionSize)
 )
)

window.myArray = Ember.SortedArrayController.create()
myArray.content.pushObjects(["Jack", "Cassandra", "Raj"])

window.myArray2 = Ember.SortedArrayController.create({sortOrder: "reverse"})
myArray2.content.pushObjects(["Jack", "Cassandra", "Raj"])

window.myArray3 = Ember.SortedArrayController.create({sortOrder: "random"})
myArray3.content.pushObjects(["Jack", "Cassandra", "Raj"])

you will get the following results:

myArray.content
["Cassandra", "Jack", "Raj"]
myArray2.content
["Raj", "Cassandra", "Jack"]
myArray3.content
["Jack", "Raj", "Cassandra"]

1 Response
Add your response

I made a gist out of the js / non-coffeescript version: https://gist.github.com/chrisjlee/31d1ea4f7cd90517b2d8

over 1 year ago ·

AltStyle によって変換されたページ (->オリジナル) /