The following example shows how you can create a custom sort on a Flex DataGrid control by using the SortField class and creating a custom compare function.
Full code after the jump.
<?xml version="1.0" encoding="utf-8"?>
<!-- http://blog.flexexamples.com/2008/04/09/creating-a-custom-sort-on-a-datagrid-control-in-flex/ -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical"
verticalAlign="middle"
backgroundColor="white">
<mx:Script>
<![CDATA[
import mx.collections.SortField;
import mx.collections.Sort;
import mx.controls.dataGridClasses.DataGridColumn;
import mx.utils.ObjectUtil;
private function sortOld():void {
var sortField:SortField = new SortField();
sortField.compareFunction = test2_compareFunc;
sortField.descending = checkBox.selected;
var oldSort:Sort = new Sort();
oldSort.fields = [sortField];
xmlListColl.sort = oldSort;
xmlListColl.refresh();
}
private function sortNew():void {
var sortField:SortField = new SortField();
sortField.compareFunction = test3_compareFunc;
sortField.descending = checkBox.selected;
var sort:Sort = new Sort();
sort.fields = [sortField];
xmlListColl.sort = sort;
xmlListColl.refresh();
}
private function resetSort():void {
xmlListColl.sort = null;
xmlListColl.refresh();
}
private function dataGridCol_labelFunc(item:XML, col:DataGridColumn):String {
return item.*.(@name == col.dataField).text();
}
private function test2_compareFunc(itemA:XML, itemB:XML):int {
var valueA:String = itemA.test2.text();
var valueB:String = itemB.test2.text();
return ObjectUtil.stringCompare(valueA, valueB);
}
private function test3_compareFunc(itemA:XML, itemB:XML):int {
var valueA:String = itemA.test3.text();
var valueB:String = itemB.test3.text();
return ObjectUtil.stringCompare(valueA, valueB);
}
]]>
</mx:Script>
<mx:XML id="tests" source="tests.xml" />
<mx:XMLListCollection id="xmlListColl" source="{tests.test}" />
<mx:ApplicationControlBar dock="true">
<mx:CheckBox id="checkBox" label="descending:" labelPlacement="left" />
<mx:Button label="Sort 'old'"
click="sortOld();" />
<mx:Button label="Sort 'new'"
click="sortNew();" />
<mx:Button label="Reset sort"
click="resetSort();" />
</mx:ApplicationControlBar>
<mx:DataGrid id="dataGrid"
dataProvider="{xmlListColl}"
width="300"
verticalScrollPolicy="on"
sortableColumns="true">
<mx:columns>
<mx:DataGridColumn dataField="old"
labelFunction="dataGridCol_labelFunc"
sortCompareFunction="test2_compareFunc" />
<mx:DataGridColumn dataField="new"
labelFunction="dataGridCol_labelFunc"
sortCompareFunction="test3_compareFunc" />
</mx:columns>
</mx:DataGrid>
</mx:Application>
tests.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- http://blog.flexexamples.com/2008/04/09/creating-a-custom-sort-on-a-datagrid-control-in-flex/ -->
<tests>
<test name="group1">
<test2 name="old">One (old)</test2>
<test3 name="new">Un (new)</test3>
</test>
<test name="group2">
<test2 name="old">Two (old)</test2>
<test3 name="new">Deux (new)</test3>
</test>
<test name="group8">
<test2 name="old">Eight (old)</test2>
<test3 name="new">Huit (new)</test3>
</test>
</tests>
View source is enabled in the following example.



{ 5 comments… read them below or add one }
Thanks! this is very useful info!!
How can sorting a datagrid be accomplished using a ComboBox?
Dave
Dave,
A bit crude, but this should work:
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" verticalAlign="middle" backgroundColor="white"> <mx:Script> <![CDATA[ import mx.events.ListEvent; import mx.collections.SortField; import mx.collections.Sort; import mx.controls.dataGridClasses.DataGridColumn; import mx.utils.ObjectUtil; private function comboBox_change(evt:ListEvent):void { var field:String = comboBox.selectedItem.sortField; var desc:Boolean = (comboBox.selectedItem.descending); var sort:Sort = new Sort(); var sortField:SortField = new SortField(); sortField.descending = desc; switch (field) { case "old": sortField.compareFunction = test2_compareFunc; break; case "new": sortField.compareFunction = test3_compareFunc; break; } sort.fields = [sortField]; xmlListColl.sort = sort; xmlListColl.refresh(); } private function resetSort():void { xmlListColl.sort = null; xmlListColl.refresh(); } private function dataGridCol_labelFunc(item:XML, col:DataGridColumn):String { return item.*.(@name == col.dataField).text(); } private function test2_compareFunc(itemA:XML, itemB:XML):int { var valueA:String = itemA.test2.text(); var valueB:String = itemB.test2.text(); return ObjectUtil.stringCompare(valueA, valueB); } private function test3_compareFunc(itemA:XML, itemB:XML):int { var valueA:String = itemA.test3.text(); var valueB:String = itemB.test3.text(); return ObjectUtil.stringCompare(valueA, valueB); } ]]> </mx:Script> <mx:XML id="tests" source="tests.xml" /> <mx:XMLListCollection id="xmlListColl" source="{tests.test}" /> <mx:Array id="arr"> <mx:Object label="Sort 'old' ascending" sortField="old" descending="false" /> <mx:Object label="Sort 'old' descending" sortField="old" descending="true" /> <mx:Object label="Sort 'new' ascending" sortField="new" descending="false" /> <mx:Object label="Sort 'new' descending" sortField="new" descending="true" /> </mx:Array> <mx:ApplicationControlBar dock="true"> <mx:ComboBox id="comboBox" dataProvider="{arr}" change="comboBox_change(event);" /> <mx:Button label="Reset sort" click="resetSort();" /> </mx:ApplicationControlBar> <mx:DataGrid id="dataGrid" dataProvider="{xmlListColl}" width="300" verticalScrollPolicy="on" sortableColumns="true"> <mx:columns> <mx:DataGridColumn dataField="old" labelFunction="dataGridCol_labelFunc" sortCompareFunction="test2_compareFunc" /> <mx:DataGridColumn dataField="new" labelFunction="dataGridCol_labelFunc" sortCompareFunction="test3_compareFunc" /> </mx:columns> </mx:DataGrid> </mx:Application>Looking back on the code, you may be able to move the
sortField.compareFunctionlogic into the ComboBox data provider array instead of using aswitchstatement in thecomboBox_change()function. I didn’t think of that the first time. You may also want to set thepromptproperty on the ComboBox.Peter
Something like this:
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" verticalAlign="middle" backgroundColor="white"> <mx:Script> <![CDATA[ import mx.events.ListEvent; import mx.collections.SortField; import mx.collections.Sort; import mx.controls.dataGridClasses.DataGridColumn; import mx.utils.ObjectUtil; private function comboBox_change(evt:ListEvent):void { var item:Object = comboBox.selectedItem; var sortField:SortField = new SortField(); sortField.descending = item.descending; sortField.compareFunction = item.compareFunc; var sort:Sort = new Sort(); sort.fields = [sortField]; xmlListColl.sort = sort; xmlListColl.refresh(); } private function resetSort():void { xmlListColl.sort = null; xmlListColl.refresh(); } private function dataGridCol_labelFunc(item:XML, col:DataGridColumn):String { return item.*.(@name == col.dataField).text(); } private function test2_compareFunc(itemA:XML, itemB:XML):int { var valueA:String = itemA.test2.text(); var valueB:String = itemB.test2.text(); return ObjectUtil.stringCompare(valueA, valueB); } private function test3_compareFunc(itemA:XML, itemB:XML):int { var valueA:String = itemA.test3.text(); var valueB:String = itemB.test3.text(); return ObjectUtil.stringCompare(valueA, valueB); } ]]> </mx:Script> <mx:XML id="tests" source="tests.xml" /> <mx:XMLListCollection id="xmlListColl" source="{tests.test}" /> <mx:Array id="arr"> <mx:Object label="Sort 'old' ascending" sortField="old" descending="false" compareFunc="{test2_compareFunc}" /> <mx:Object label="Sort 'old' descending" sortField="old" descending="true" compareFunc="{test2_compareFunc}" /> <mx:Object label="Sort 'new' ascending" sortField="new" descending="false" compareFunc="{test3_compareFunc}" /> <mx:Object label="Sort 'new' descending" sortField="new" descending="true" compareFunc="{test3_compareFunc}" /> </mx:Array> <mx:ApplicationControlBar dock="true"> <mx:ComboBox id="comboBox" dataProvider="{arr}" prompt="Please select a sort..." change="comboBox_change(event);" /> <mx:Button label="Reset sort" click="resetSort();" /> </mx:ApplicationControlBar> <mx:DataGrid id="dataGrid" dataProvider="{xmlListColl}" width="300" verticalScrollPolicy="on" sortableColumns="true"> <mx:columns> <mx:DataGridColumn dataField="old" labelFunction="dataGridCol_labelFunc" sortCompareFunction="test2_compareFunc" /> <mx:DataGridColumn dataField="new" labelFunction="dataGridCol_labelFunc" sortCompareFunction="test3_compareFunc" /> </mx:columns> </mx:DataGrid> </mx:Application>Peter
Thany you for your code.
First I click the DataGrid’s header, there’s a small black triangle to show where it is working on.
Then I click the buttons upside, to resort the DataGrid. Can the small black triangle change the meantime?
Thanks Peter, this is awesome!!