Sometimes in life you just need data to be sorted. Whether its a case insensitive sort (for names) or a numeric sort (for, uh, numbers), you just want things sorted in a particular order.
This example demonstrates how you can take a bunch of random numbers in an ArrayCollection and sort them numerically in ascending order.
Full code after the jump.
Download source (ZIP, 1K) | View MXML
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" verticalAlign="middle" backgroundColor="white" creationComplete="init()">
<mx:Script>
<![CDATA[
import mx.collections.SortField;
import mx.collections.Sort;
import mx.collections.ArrayCollection;
[Bindable]
private var arrColl:ArrayCollection;
/** This method gets called by the main mx:Application tag and initializes/populates the ArrayCollection object with a bunch of random numbers. */
private function init():void {
var i:int;
/* Initialize and populate the ArrayCollection object. */
arrColl = new ArrayCollection();
for (i = 0; i < 20; i++) {
arrColl.addItem({data:getRandomNumber().toFixed(4)});
}
}
/** This method returns a random floating-point number between 0 and 10000. */
private function getRandomNumber():Number {
return Math.random() * 10000;
}
/** This method gets called by the Button control's click handler and creates a new SortField and Sort object which are used to sort the ArrayCollection. */
private function button_click():void {
/* Create the SortField object for the "data" field in the ArrayCollection object, and make sure we do a numeric sort. */
var dataSortField:SortField = new SortField();
dataSortField.name = "data";
dataSortField.numeric = true;
/* Create the Sort object and add the SortField object created earlier to the array of fields to sort on. */
var numericDataSort:Sort = new Sort();
numericDataSort.fields = [dataSortField];
/* Set the ArrayCollection object's sort property to our custom sort, and refresh the ArrayCollection. */
arrColl.sort = numericDataSort;
arrColl.refresh();
}
]]>
</mx:Script>
<mx:List id="list" dataProvider="{arrColl}" textAlign="right" labelField="data" width="100" />
<mx:Button id="button" label="sort items" click="button_click()" />
</mx:Application>
View source is enabled in the following example.

{ 28 comments… read them below or add one }
Thanks for the tip. Really useful. It would be also useful to know that to sort descending you need to add “dataSortField.descending = true;”
Have phun,
Andrei
If an ArrayCollection contains a number of Foo objects and Foo has an attribute an instance of the class Bar and Bar has an attribute of fizz, can a SortField be used to sort Foo’s by the fizz attribute? I’ve tried doing new SortField(‘bar.fizz’) but get a runtime error stating that bar.fizz isn’t a property of Foo — even though it is. Is there any way around this?
There is great!
Hey Peterd, if I want to sort by text what code should I replace for below?
dataSortField.numeric = true;
Thanks
valentineday,
I haven’t tested it, but you could either try passing “false”, or perhaps just comment out/delete that line altogether.
Also, if you want to do a non-case-sensitive text search, you may want to try setting the
caseInsensitiveproperty totrue.Peter
Hi,
I’m looking for the same answer for as Peter stated [is there a one..?];
peter Oct 3rd, 2007 at 12:51 pm
If an ArrayCollection contains a number of Foo objects and Foo has an attribute an instance of the class Bar and Bar has an attribute of fizz, can a SortField be used to sort Foo’s by the fizz attribute? I’ve tried doing new SortField(’bar.fizz’) but get a runtime error stating that bar.fizz isn’t a property of Foo — even though it is. Is there any way around this?
thanks,
-bader
Hi,
I to, am looking for a solution to the same problem as bader & peter
(If an ArrayCollection contains a number of Foo objects and Foo has an attribute an instance of the class Bar and Bar has an attribute of fizz, can a SortField be used to sort Foo’s by the fizz attribute? I’ve tried doing new SortField(’bar.fizz’) but get a runtime error stating that bar.fizz isn’t a property of Foo — even though it is. Is there any way around this?)
You see i needed to use a itemRenderer for each column in my datagrid meaning that i had to populate each column using the code “data.etc”, the problem comes into play when i want to sort a column that displays a child element of one of the objects in my arrayCollection, how do i go about doin this? Been battling for a day or two.
thanks,
jason
Hi,
Could you please give me an example to sort numeric data in XMLListCollection? Here is my sample XML
Thanks,
VIvke
vivek,
Here’s an example of sorting XMLListCollection using MXML and ActionScript:
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:Script> <![CDATA[ import mx.collections.SortField; import mx.collections.Sort; private function sortByField(value:String, isNumeric:Boolean = false, isDescending:Boolean = false):Boolean { var sortField:SortField = new SortField(value); sortField.numeric = isNumeric; sortField.descending = isDescending; var sort:Sort = new Sort(); sort.fields = [sortField]; xmlListColl.sort = sort; return xmlListColl.refresh(); } ]]> </mx:Script> <mx:XMLListCollection id="xmlListColl"> <mx:source> <mx:XMLList> <group name="Esthetique" value="2997" cost="0.52" /> <group name="xx" value="652" cost="0.47" /> <group name="xyt" value="652" cost="0.54" /> <group name="sss" value="652" cost="0.23" /> <group name="ffsdfsd" value="652" cost="0.82" /> </mx:XMLList> </mx:source> <mx:sort> <mx:Sort> <mx:SortField name="@cost" numeric="true" descending="true" /> </mx:Sort> </mx:sort> </mx:XMLListCollection> <mx:Panel> <mx:DataGrid dataProvider="{xmlListColl}" width="100%"> <mx:columns> <mx:DataGridColumn dataField="@name" /> <mx:DataGridColumn dataField="@cost" /> <mx:DataGridColumn dataField="@value" /> </mx:columns> </mx:DataGrid> <mx:ControlBar> <mx:Button label="Sort by @name" click="sortByField('@name')" /> <mx:Button label="Sort by @cost" click="sortByField('@cost', true, true);" /> <mx:Button label="Sort by @value" click="sortByField('@value', true, true);" /> </mx:ControlBar> </mx:Panel> </mx:Application>Happy Flexing!
Peter
For another example of sorting XMLListCollection, see “Sorting XML documents using an XMLListCollection”.
Peter
This might be a really silly question, but how do you sort if instead of objects your array just contains strings, like this:
[0] = “a”;
[1] = “c”;
[2] = “b”;
What sort field would you use for that?!
Paul.
Paul,
Just use the simple sort!
If I call sort on a list then add any new items, do i have to ‘resort’ on each insert or is it automatic now that a sort instance has been applied to the list?
Dan,
I quickly tested and it appears that newly added items are automatically added into their sorted position.
Peter
It doesnt seem to be sorting very well for me, I seem to have some that are unsorted; are there any known bugs with this that you know?
I’m looking for the same example as peter and bader – ac.getItemAt(i).bar.fizz sorting – would love help w/ that!
How would one go about sorting by date? Do I need to create a custom comparitor? Thanks!
Tom,
Turns out that I have an example on that very topic: http://blog.flexexamples.com/2007/08/12/sorting-date-columns-in-a-datagrid/
Peter
hey very useful example thanks. I wanna know if the list constructed as sorted. I mean do we have to click sort button? Couldn’t we show the list sorted at initialization?
I need to loop thru my collection AFTER its sorted, but when I do I get empty data. Is there a trick to this?
maybe I should clarify… I have some XML data, a list of strings, say peoples names for instance. I want to sort the list, then number them, then insert a “Select All” at the top of the list (index zero). I can seem to either number them or sort them but not both. Immediately after I sort (and refresh), I try to loop through the newly sorted list but get empty values during a trace()??? This is where I would want to add in my numbering and also insert my “Select All” item.
Any thoughts here?
is there a trick to sorting on multiple object attributes in an array list?
@Anonymous,
None I can think of off the top of my head. Are you having a specific problem trying to sort by multiple properties?
Peter
Adobe Flex – Sorting an ArrayColleciton by Date
http://kuriakosejacobthomas.blogspot.com/2009/10/adobe-flex-sorting-arraycolleciton-by.html
Adobe Flex – Sorting an ArrayColleciton by Date
/**
* @params data:Array
* @return dataCollection:Array
**/
private function orderByPeriod(data:Array):Array
{
var dataCollection:ArrayCollection = new ArrayCollection(data);//Convert Array to ArrayCollection to perform sort function
var dataSortField:SortField = new SortField();
dataSortField.name = “period”; //Assign the sort field to the field that holds the date string
var numericDataSort:Sort = new Sort();
numericDataSort.fields = [dataSortField];
dataCollection.sort = numericDataSort;
dataCollection.refresh();
return dataCollection.toArray();
}
A few gotchas when working with ArrayCollections.
When sorting an ArrayCollection, any further items will be auto sorted. Even if you’re adding items through the source.contact() method.
It is best to to create a temporary copy of an ArrayCollection to be sorted. Sort it using the new Sort() object, then when done, copy back the sorted elements using .toArray(); and NOT the source.concat().
If you are using a class level ArrayCollection that has been sorted, and you are extending the parent class that this is declared in, adding items via the child class will be auto sorted unless you have sorted the collection through a proxy temporary local collection.
Best practice:
MyClassLevelCollection.disableAutoUpdate();
//creat temporary ArrayCollection for sorting.
//Then copy them back to the class level ArrayCollection
var tempLocalCollection:ArrayCollection = new ArrayCollection();
tempLocalCollection.source = MyClassLevelCollection.toArray();
var dataSortField:SortField = new SortField();
dataSortField.name = “CountryValue”;
dataSortField.numeric = true;
dataSortField.descending = true;
tempLocalCollection.sort = new Sort();
tempLocalCollection.sort.fields = [dataSortField];
tempLocalCollection.refresh();
//add the newly sorted objects
MyClassLevelCollection.source = tempLocalCollection.toArray();
MyClassLevelCollection.enableAutoUpdate();
Thanks Peter, but especially thanks to Chris.
My issue is that I’m not able to preserve the sort for some reason. The following displays accurately, but the sort is not preserved (date descending) on subsequent calls.
thanks for this very useful tip. It helps me, to sort my datagrid which is based on an array collection
Hi, i’m actually sorting directly on the Array source of the ArrayCollection, which you’ll see is done using just two lines of code, instead of instianciating Sort / SortField classes. It works for me, i don’t know how much it’ll impact the performances of bigger apps, but hey… that’s a nice workaround at least :)
var myAC:ArrayCollection = new ArrayCollection();
for ( var i:int = 0; i < 10; i++ ) {
myAC.addItem( { data: int(Math.random() * 200) } );
}
myAC.source.sortOn('data', Array.NUMERIC);
myAC.refresh();