Sorting date columns in a DataGrid
Here’s an example of sorting a column of dates in a Flex DataGrid. The dates start out as Strings (such as “04/14/1980″) so you create a custom sortCompareFunction on that DataGrid column which converts the strings to dates so Flex will sort the dates in sequential order (as oppsed to string order). Hope that helps somebody out there.
I also created a little tooltip on the date column which shows the dates in a somewhat more readable form (“April 14 1980″) using the DataGridColumn object’s showDataTips and dataTipFunction properties.
Full code after the jump.
<?xml version="1.0" encoding="utf-8"?> <!-- http://blog.flexexamples.com/2007/08/12/sorting-date-columns-in-a-datagrid/ --> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" verticalAlign="middle" backgroundColor="white"> <mx:Script> <![CDATA[ import mx.utils.ObjectUtil; private function date_sortCompareFunc(itemA:Object, itemB:Object):int { /* Date.parse() returns an int, but ObjectUtil.dateCompare() expects two Date objects, so convert String to int to Date. */ var dateA:Date = new Date(Date.parse(itemA.dob)); var dateB:Date = new Date(Date.parse(itemB.dob)); return ObjectUtil.dateCompare(dateA, dateB); } private function date_dataTipFunc(item:Object):String { return dateFormatter.format(item.dob); } ]]> </mx:Script> <mx:ArrayCollection id="arrColl"> <mx:source> <mx:Array> <mx:Object name="User A" dob="04/14/1980" /> <mx:Object name="User B" dob="01/02/1975" /> <mx:Object name="User C" dob="12/30/1977" /> <mx:Object name="User D" dob="10/27/1968" /> </mx:Array> </mx:source> </mx:ArrayCollection> <mx:DateFormatter id="dateFormatter" formatString="MMMM D, YYYY" /> <mx:DataGrid id="dataGrid" dataProvider="{arrColl}"> <mx:columns> <mx:DataGridColumn dataField="name" headerText="Name:" /> <mx:DataGridColumn dataField="dob" headerText="Date of birth:" sortCompareFunction="date_sortCompareFunc" showDataTips="true" dataTipFunction="date_dataTipFunc" /> </mx:columns> </mx:DataGrid> </mx:Application>
View source is enabled in the following example.
Peter deHaan
Peter deHaan currently works for Adobe on the Flex SDK QA team. While not working on Flex, Flash, and ColdFusion applications, Peter enjoys making up bios and writing in 3rd person. Peter's rarely updated blog can be found at blogs.adobe.com/pdehaan/, actionscriptexamples.com, airexamples.com, and coldfusionexamples.com.
-
Add Widgets (Content Sidebar)
This is your Content Sidebar. Edit this content that appears here in the widgets panel by adding or removing widgets in the Content Sidebar area.
38 Responses to Sorting date columns in a DataGrid
Leave a Reply Cancel reply
-
Categories
- Accordion
- AccordionHeader
- ActionScript
- AddChild
- AdvancedDataGrid
- Alert
- alpha
- Animate
- AnimateProperties
- Application
- Application (Spark)
- ArrayCollection
- BarChart
- baseColor
- beta
- beta1
- beta2
- Bitmap
- Bitmap/BitmapData
- BitmapData
- BitmapFill
- BitmapFill (Spark)
- BitmapGraphic
- BitmapImage
- BitmapImage (Spark)
- BitmapImageResizeMode
- Border (Spark)
- BorderContainer (Spark)
- Box
- BuildInfo
- Button
- Button (Spark)
- ButtonBar
- ButtonBar (Spark)
- ByteArray
- Camera
- Charting
- CheckBox
- CheckBox (Spark)
- ClassFactory
- CollectionEvent
- Color
- ColorPicker
- ColorUtil
- ComboBox
- ComboBoxArrowSkin
- Compiler
- Component
- Component (Spark)
- Configuration
- Container
- ContextMenu
- ContextMenuEvent
- ContextMenuItem
- CSSCondition
- CSSSelector
- CSSStyleDeclaration
- CurrencyFormatter
- CursorManager
- Data Binding
- DataGrid
- DataGrid (Spark)
- DataGridColumn
- Date
- DateBase
- DateChooser
- DateField
- DateFormatter
- Debugging
- DefaultComplexItemRenderer
- DefaultTileListEffect
- DropDownList
- DropDownList (Spark)
- DropDownListButtonSkin
- DropDownListSkin
- DropShadowFilter
- E4X
- Effects
- Ellipse
- EmailValidator
- Embed
- Event
- Fade
- FileFilter
- FileReference
- fill
- Filters
- Flash
- Flash Integration
- FlashVars
- Flex 3 SDK
- Flex Builder
- Flex Builder 3
- Flex SDK
- Flex4
- FLVPlayback
- FocusManager
- FontLookup
- Fonts
- Form
- Form (Spark)
- FormHeading (Spark)
- FormItem
- FormItem (Spark)
- Forms
- FTETextField (Spark)
- FullScreen
- FullScreenEvent
- FxAnimateColor
- FxButtonBar
- FxCheckBox
- FXG
- FxHScrollBar
- FxHSlider
- FxList
- FxNumericStepper
- FxRadioButton
- FxRotate3D
- FxScroller
- FxTextArea
- FxTextInput
- FxToggleButton
- FxVScrollBar
- FxVSlider
- getStyleDeclaration()
- GradientEntry
- Graphic (Spark)
- HBox
- HDividedBox
- HGroup (Spark)
- HorizontalLayout
- HorizontalList
- HSBColor (Spark)
- HScrollBar (Spark)
- HSlider
- HSlider (Spark)
- HTML template
- ID3Info
- Image
- Image (Spark)
- ImageSnapshot
- itemRenderer
- JointStyle
- Label
- Label (Spark)
- Legend
- LegendItem
- LigatureLevel
- Line
- LinearGradientStroke
- LineScaleMode
- LinkBar
- LinkButton
- List
- List (Spark)
- Menu
- MenuBar
- Metadata
- MetadataEvent
- Model
- Mouse
- MouseCursor
- MouseEvent
- Move
- Namespace
- NavigatorContent (Spark)
- needsSWF
- NetConnection
- NetStream
- Nightly Builds
- NumberBaseRoundType
- NumberFormatter
- NumberValidator
- NumericCompare
- NumericStepper
- NumericStepper (Spark)
- ObjectProxy
- ObjectUtil
- paddingLeft
- paddingRight
- Panel
- Panel (Spark)
- Parallel
- Path
- PieChart
- PieSeries
- PieSeriesItem
- PopUpAnchor (Spark)
- PopUpButton
- PopUpManager
- ProgrammaticSkin
- ProgressBar
- PropertyChangeEvent
- QName
- RadialGradient
- RadioButton
- RadioButton (Spark)
- RadioButtonGroup
- RadioButtonGroup (Spark)
- Rect
- RegExp
- Regular Expressions
- Repeater
- RichEditableText
- RichText
- RichText (Spark)
- RichTextEditor
- Rotate
- Rotate3D (Spark)
- Scroller (Spark)
- Sequence
- setStyle()
- SimpleText
- SimpleText (Spark)
- skinClass
- Slider
- SliderEvent
- SolidColor
- SolidColorStroke
- Sort
- SortField
- Sound
- SoundEffect
- Spinner (Spark)
- SpriteVisualElement (Spark)
- StageDisplayState
- States
- StringUtil
- StringValidator
- StyleManager
- Styles
- SWFLoader
- SWFObject
- System
- SystemManager
- TabBar
- TabBar (Spark)
- TabNavigator
- TabStopFormat
- Text
- Text Layout Framework (TLF)
- TextArea
- TextArea (Spark)
- TextBox
- TextConverter
- TextEvent
- TextFlow
- TextFlowUtil
- TextFormat
- TextGraphic
- TextInput
- TextInput (Spark)
- TextLayoutFormat
- TextView
- Themes
- TileLayout
- TileList
- TileOrientation
- Timer
- TitleWindow
- TitleWindow (Spark)
- TLF
- ToggleButton (Spark)
- ToggleButtonBar
- ToolTip
- Transition
- Tree
- TruncationOptions
- UIComponent
- UIFTETextField
- Updater
- URLLoader
- URLRequest
- URLUtil
- URLVariables
- ValidationResultEvent
- Validator
- Validators
- VBox
- VDividedBox
- Vector
- VerticalLayout
- VerticalLayout (Spark)
- VGroup (Spark)
- Video
- VideoDisplay
- VideoElement
- VideoElement (Spark)
- VideoEvent
- VideoPlayer (Spark)
- VideoPlayerScrubBar
- ViewStack
- VScrollBar (Spark)
- VSlider
- VSlider (Spark)
- XML
- XMLList
- XMLListCollection
- ZipCodeValidator
- ZipCodeValidatorDomainType
- Zoom
-
Articles
- December 2010
- November 2010
- October 2010
- September 2010
- August 2010
- July 2010
- June 2010
- May 2010
- April 2010
- March 2010
- February 2010
- January 2010
- December 2009
- November 2009
- October 2009
- September 2009
- August 2009
- July 2009
- June 2009
- May 2009
- April 2009
- March 2009
- February 2009
- January 2009
- December 2008
- November 2008
- October 2008
- September 2008
- August 2008
- July 2008
- June 2008
- May 2008
- April 2008
- March 2008
- February 2008
- January 2008
- December 2007
- November 2007
- October 2007
- September 2007
- August 2007
- July 2007
-
Meta


I don’t quite see why the dates are strings in your data, why not use date objects to start with?
Anyway, if you want you can sort the int’s returned by Date.parse like this:
private function dateComparator( itemA : Object, itemB : Object ) : int { var a : int = Date.parse(itemA.dob); var b : int = Date.parse(itemB.dob); return (b - a)/Math.abs(b - a); }what happened if a==b?
Theo,
The dates were strings instead of date objects, well, for no real reason. If they were dates to begin with, I believe they would have sorted properly without any additional code being needed. Although, if you were getting the data from an XML document or something else, its likely they would have imported as Strings.
Also, looking again at the ObjectUtil documentation, it looks like I could have skipped converting to dates and used the
ObjectUtil.numericCompare()method, or your code works great too.Good tip, thanks.
No, dates aren’t sorted right by default. I’ve tried a few times and it always surprises me that DataGrid doesn’t support it by default, it’s such an obvious feature.
I’m not sure why but they end up ordered in a way that looks quite random to me. I can imagine that they are ordered either by their toString value or some other date string format that doesn’t support ordering.
They’re sorted alphabetically – a rather irritating choice for a default date sort.
I like to keep my dates in the database as YYYY-MM-DD, this way they sort without help. Then all you need is a labelFunction to display them as you like them.
how do u make this sort function generic i.e if you have many numeric columns in a datagrid, do you need to write a comparator function for each column?
sm,
Not sure if there is a better way, but this was the first idea that came to mind. Surprisingly, it seems to work, based on my approximate 90 seconds of testing.
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical"> <mx:Script> <![CDATA[ import mx.utils.ObjectUtil; private var col:String; private function numericSort(itemA:Object, itemB:Object):int { return ObjectUtil.numericCompare(itemA[col], itemB[col]); } ]]> </mx:Script> <mx:Array id="arr"> <mx:Object name="one" col1="1" col2="0.59" col3="1.5" col4="40" /> <mx:Object name="two" col1="2" col2="0.32" col3="1.1" col4="-12" /> <mx:Object name="three" col1="3" col2="0.82" col3="2.9" col4="22" /> <mx:Object name="four" col1="4" col2="0.29" col3="-0.2" col4="25" /> <mx:Object name="five" col1="5" col2="0.33" col3="5.0" col4="37" /> <mx:Object name="six" col1="6" col2="0.51" col3="-2.3" col4="-11" /> <mx:Object name="seven" col1="7" col2="0.70" col3="4.1" col4="-9" /> </mx:Array> <mx:DataGrid id="dataGrid" dataProvider="{arr}" headerRelease="col = dataGrid.columns[event.columnIndex].dataField;"> <mx:columns> <mx:DataGridColumn dataField="name" /> <mx:DataGridColumn dataField="col1" sortCompareFunction="numericSort" /> <mx:DataGridColumn dataField="col2" sortCompareFunction="numericSort" /> <mx:DataGridColumn dataField="col3" sortCompareFunction="numericSort" /> <mx:DataGridColumn dataField="col4" sortCompareFunction="numericSort" /> </mx:columns> </mx:DataGrid> </mx:Application>Hope that helps,
Peter
Thanks Peter!Actually I have a datagrid that is getting generated dynamically using actionscript. The sortcomparefunction seems to work when i put it in the mxml tag but when i try using it in actionscript it fails!
eg if i do
in the mx:Script tags
sm,
Does the following work for you? Note that I have a slight “workaround” where I’m storing the currently selected header by listening for the data grid control’s
headerReleaseevent.<?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.events.DataGridEvent; import mx.controls.dataGridClasses.DataGridColumn; import mx.controls.DataGrid; import mx.utils.ObjectUtil; private var dataGrid:DataGrid; private var col:String; private function init():void { /* name column */ var nameCol:DataGridColumn = new DataGridColumn("name"); /* col1 column */ var col1Col:DataGridColumn = new DataGridColumn("col1"); col1Col.sortCompareFunction = numericSort; /* col2 column */ var col2Col:DataGridColumn = new DataGridColumn("col2"); col2Col.sortCompareFunction = numericSort; /* col3 column */ var col3Col:DataGridColumn = new DataGridColumn("col3"); col3Col.sortCompareFunction = numericSort; /* col4 column */ var col4Col:DataGridColumn = new DataGridColumn("col4"); col4Col.sortCompareFunction = numericSort; var cols:Array = []; cols.push(nameCol); cols.push(col1Col); cols.push(col2Col); cols.push(col3Col); cols.push(col4Col); dataGrid = new DataGrid(); dataGrid.dataProvider = arr; dataGrid.columns = cols; dataGrid.addEventListener(DataGridEvent.HEADER_RELEASE, dataGrid_headerRelease); addChild(dataGrid); } private function dataGrid_headerRelease(evt:DataGridEvent):void { col = dataGrid.columns[evt.columnIndex].dataField; } private function numericSort(itemA:Object, itemB:Object):int { return ObjectUtil.numericCompare(itemA[col], itemB[col]); } ]]> </mx:Script> <mx:Array id="arr"> <mx:Object name="one" col1="1" col2="0.59" col3="1.5" col4="40" /> <mx:Object name="two" col1="2" col2="0.32" col3="1.1" col4="-12" /> <mx:Object name="three" col1="3" col2="0.82" col3="2.9" col4="22" /> <mx:Object name="four" col1="4" col2="0.29" col3="-0.2" col4="25" /> <mx:Object name="five" col1="5" col2="0.33" col3="5.0" col4="37" /> <mx:Object name="six" col1="6" col2="0.51" col3="-2.3" col4="-11" /> <mx:Object name="seven" col1="7" col2="0.70" col3="4.1" col4="-9" /> </mx:Array> </mx:Application>thanks for a great solution!
when you replace the line:
col = dataGrid.columns[evt.columnIndex].dataField;
with:
col = evt.dataField;
you will be able to use it with multiple datagrids
Hey Peter,
I tried your solution given to SM, however it does not work for me.
Note that my DG dataProvider is a xml of type
I have tried to use the numericsort function but it does not sort correctly, also it stops working completely after first click on the header of creationData column.
Can you please suggest..
Thanks,
Thanks a million Peter!!!u r a godsend!!that did work..i have been stuck on it fr 3 days and with such little examples on dynamic grids available online your help really meant a lot to me!!!
Glad I could help. I also highly recommend subscribing to the FlexCoders mailing list, if you haven’t already. (see http://flex.org/community/#mailinglists for links and details on various Flex-related mailing lists)
At over 7650 members, it is quite an active and informative list. Although one word of warning, it can get very busy (~3000 posts a month), so make sure you set up the appropriate filters otherwise your inbox can get a bit overwhelmed.
Happy Flexing!
Peter
Thanks. I definitely need a lot of information with Flex and m going to join this community right away!
Thanks for the post. It is useful as the data I get from a webservice is in the form of string as u used.
This is super useful code dude :)
Hi,
I want to have a generic date_sortCompareFunc function for all the datagrid’s in my application. Is it possible to pass an extra parameter to this function. Basically I want to pass the object field on which the sort function should work.
AM
AM,
I don’t believe you can, since those parameters get passed from Flex. Although you may be able to extend DataGrid and/or DataGridColumn and add that functionality.
You could try asking on the FlexCoders mailing list and see if anybody has some suggestions.
Peter
if we have a non standard date format:
If you have multiple numeric column to sort i think it is better to have something like that :
And in your mxml for each numeric column :
Hum bug because of the tags:
So in your mxml :
<mx:DataGridColumn dataField="theFieldName" sortCompareFunction="numericSort('theFieldName')" />Any way to do this type of sorting with Time-strings?
I used the date sorting example to sort one date field in my window but I have 10 more date fields in the same window and I would like to make those sortable as well. Do I need to create a seperate function for each date field or is there a way to create one function to handle all 11 date fields?
Thanks,
Vicki
Vicki,
I believe since I hardcoded the
dataFieldproperty (“dob”) in the sort function itself (date_sortCompareFunc()), you’d need 10 separate functions, although you could probably come up with a way to dynamically.In fact, I haven’t tried this solution personally, but you could try this: http://justinjmoses.wordpress.com/2008/03/11/generic-flex-datagrid-case-insensitive-sort/
Peter
Peter,
Thanks but that’s just it, I didn’t want to create 10 seperate functions. I have a feeling this is the only way to do it, unfortunately. Since I am just starting out in Flex (this is my first project), I have no clue how to dynamically do this or anything yet. Thanks so much for responding though.
Vicki
Vicki,
This should work: http://justinjmoses.wordpress.com/2008/03/11/generic-flex-datagrid-case-insensitive-sort/
If not, let me know and we can try and take a look.
Peter
According to the current docs (22 September 09),
Date.parse()is Air SDK only… though it appears to work fine for me.http://livedocs.adobe.com/flex/gumbo/langref/Date.html#parse%28%29
@Tim Oxley,
Great question. Feel free to file a bug at http://bugs.adobe.com/flex/ against the Flex Documentation project. Also, I can ask somebody to take a quick look as to why that is marked AIR only. It seems to be that way in the Flex 3 documentation also.
Peter
http://kuriakosejacobthomas.blogspot.com/2009/10/adobe-flex-sorting-arraycolleciton-by.html
Hi,
if ever the date i want to display is of format: “DD/MM/YYYY”.
How does that one goes?
Thanks in advance …
David
@DAvid,
See jalal’s suggestion above: http://blog.flexexamples.com/2007/08/12/sorting-date-columns-in-a-datagrid/#comment-563
Peter
This is a great solutio. One small problem that I have found. In a practical situation you could have rows in your datagrid that do not have a date filled in. Idealy you would want these dates to appear first or last when you sort by your date collumn. However I have found that this solution as is does not take that into consideration. When you trace this out and look at both dates you will notice that if there is no value in the specific row you are looking at the date will show up as NaN. This of course is expected obviously you can not convert a null value to a date. If you keep tracing it out you will notice that depending on which way you are trying to sort accending or decending one of the two dates dateA, and dateB will always have a value. if dateA = NaN you want to return -1 if dateB = NaN you want to return 1 otherwise let this function do its job. So if you add the following lines to this function this is a perfect solution
if(dateA.time.toString() == “NaN”){
return -1
}// end if
else if(dateB.time.toString() == “NaN”){
return 1
}// end if
obviosuly you will have to put the original return statement in the else case as follows
else{
return ObjectUtil.dateCompare(dateA, dateB);
}// end else
Hope this helps
Thanks again for this solution
We actually have a grid that solves the issue of sorting/filtering by dates/numbers/booleans where the actual data is string and a intermediate conversion is required before the sort/filter operation. Please take a look at http://www.flexicious.com.
http://raflabs.com/blogs/silence-is-foo/2010/06/28/creating-a-common-sorting-function-for-a-datagrid-control-in-flex/
Sometimes I’m in the situation where I need to use the same complex sorting function for several datagrids, here’s my solution.
Terrific. Exactly what I needed !
Is it possible to write a common component for sorting which can be used by multiple datagrids , also keeping in mind columns can be numeric , alphanumeric & String Data type. If anything like this is possible , it will solve my problem
Thanks
Giri
Hi Peter,
What is the event that gets fired when you click on a datagrid column to sort it?