Displaying the sort arrow in a Flex DataGrid control without having to click a column
I’ve seen this question come up a few times recently in various forums/lists and even in my blog comments (see “Changing the default sort arrow skin on a Flex DataGrid control”).
The following example shows how you can display the sort arrow in a DataGrid control in Flex without having the user click on a column header in the DataGrid control.
Full code after the jump.
<?xml version="1.0" encoding="utf-8"?> <!-- http://blog.flexexamples.com/2008/02/28/displaying-the-sort-arrow-in-a-flex-datagrid-control-without-having-to-click-a-column/ --> <mx:Application name="DataGrid_dataProvider_sort_fields_test"> xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" verticalAlign="middle" backgroundColor="white"> <mx:Script> <![CDATA[ import mx.collections.Sort; import mx.collections.SortField; private function init():void { arrColl.sort = new Sort(); arrColl.sort.fields = [new SortField("idx", false, true)]; arrColl.refresh(); } ]]> </mx:Script> <mx:ArrayCollection id="arrColl"> <mx:source> <mx:Array> <mx:Object idx="1" c1="One.1" c2="One.2" /> <mx:Object idx="2" c1="Two.1" c2="Two.2" /> <mx:Object idx="3" c1="Three.1" c2="Three.2" /> <mx:Object idx="4" c1="Four.1" c2="Four.2" /> <mx:Object idx="5" c1="Five.1" c2="Five.2" /> <mx:Object idx="6" c1="Six.1" c2="Six.2" /> <mx:Object idx="7" c1="Seven.1" c2="Seven.2" /> <mx:Object idx="8" c1="Eight.1" c2="Eight.2" /> <mx:Object idx="9" c1="Nine.1" c2="Nine.2" /> <mx:Object idx="10" c1="Ten.1" c2="Ten.2" /> <mx:Object idx="11" c1="Eleven.1" c2="Eleven.2" /> <mx:Object idx="12" c1="Twelve.1" c2="Twelve.2" /> <mx:Object idx="13" c1="Thirteen.1" c2="Thirteen.2" /> </mx:Array> </mx:source> </mx:ArrayCollection> <mx:DataGrid id="dataGrid" dataProvider="{arrColl}" creationComplete="init();"> <mx:columns> <mx:DataGridColumn dataField="idx" /> <mx:DataGridColumn dataField="c1" /> <mx:DataGridColumn dataField="c2" /> </mx:columns> </mx:DataGrid> </mx:Application>
View source is enabled in the following example.
A big thanks to Rob for the heads up with the solution!
For more information, see http://bugs.adobe.com/jira/browse/SDK-14663.
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.
34 Responses to Displaying the sort arrow in a Flex DataGrid control without having to click a column
-
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


Thanks for this helpful post, glad to see that it’s not only me that has had this problem, much appreciated, keep up the good work!
The solution is good, but I just want to know is there any way that we can showed the up/down arrow without having to refresh (sort) the grid data provider.
Is there a way to programatically get the last column sort? In otherwords say the user has clicked on a particular column header, how would you store the sort associated with that header, along with its direction?
Bill J,
Not sure if this is the best solution, but it seems to 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.DataGridEvent; private function dataGrid_headerRelease(evt:DataGridEvent):void { // Hang out a while, wait a frame. callLater(delayedSet, [evt]); } private function delayedSet(evt:DataGridEvent):void { lbl1.text = evt.dataField; lbl2.text = dataGrid.columns[evt.columnIndex].sortDescending; } ]]> </mx:Script> <mx:Array id="arr"> <mx:Object idx="1" c1="One.1" c2="One.2" /> <mx:Object idx="2" c1="Two.1" c2="Two.2" /> <mx:Object idx="3" c1="Three.1" c2="Three.2" /> <mx:Object idx="4" c1="Four.1" c2="Four.2" /> <mx:Object idx="5" c1="Five.1" c2="Five.2" /> <mx:Object idx="6" c1="Six.1" c2="Six.2" /> </mx:Array> <mx:DataGrid id="dataGrid" dataProvider="{arr}" headerRelease="dataGrid_headerRelease(event);"> <mx:columns> <mx:DataGridColumn dataField="idx" /> <mx:DataGridColumn dataField="c1" /> <mx:DataGridColumn dataField="c2" /> </mx:columns> </mx:DataGrid> <mx:Form> <mx:FormItem label="dataField:"> <mx:Label id="lbl1" /> </mx:FormItem> <mx:FormItem label="sortDescending:"> <mx:Label id="lbl2" /> </mx:FormItem> </mx:Form> </mx:Application>If you use an ArrayCollection or XMLListCollection as a data provider, you may be able to access the collection’s underlying
sortproperty and determine the sort order as well.In fact, here’s what that would look like too:
<?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.collections.SortField; import mx.events.DataGridEvent; private function dataGrid_headerRelease(evt:DataGridEvent):void { // Hang out a while, wait a frame. callLater(delayedSet, [evt]); } private function delayedSet(evt:DataGridEvent):void { var sortField:SortField = arrColl.sort.fields[0] as SortField; lbl1.text = sortField.name; lbl2.text = sortField.descending.toString(); } ]]> </mx:Script> <mx:ArrayCollection id="arrColl"> <mx:source> <mx:Array> <mx:Object idx="1" c1="One.1" c2="One.2" /> <mx:Object idx="2" c1="Two.1" c2="Two.2" /> <mx:Object idx="3" c1="Three.1" c2="Three.2" /> <mx:Object idx="4" c1="Four.1" c2="Four.2" /> <mx:Object idx="5" c1="Five.1" c2="Five.2" /> <mx:Object idx="6" c1="Six.1" c2="Six.2" /> </mx:Array> </mx:source> </mx:ArrayCollection> <mx:DataGrid id="dataGrid" dataProvider="{arrColl}" headerRelease="dataGrid_headerRelease(event);"> <mx:columns> <mx:DataGridColumn dataField="idx" /> <mx:DataGridColumn dataField="c1" /> <mx:DataGridColumn dataField="c2" /> </mx:columns> </mx:DataGrid> <mx:Form> <mx:FormItem label="dataField:"> <mx:Label id="lbl1" /> </mx:FormItem> <mx:FormItem label="sortDescending:"> <mx:Label id="lbl2" /> </mx:FormItem> </mx:Form> </mx:Application>Again, I make no claims this is the “best” approach, just the first thing that came to mind at 7:40am. :)
Peter
Hieu Lam,
I don’t believe there is a way to show a sort arrow without refreshing the data provider. Or maybe there is, and I just don’t know about it (very likely).
If you haven’t found a solution yet (and are still reading comments), I suggest asking on the FlexCoders mailing list and seeing if anybody there has any ideas.
Peter
Just looking at the DataGrid source I dont think there is a way to update it without refreshing the list.
There is a private method on the grid, called UpdateSortIndexAndDirection which is private. Internally it sets the sortIndex and last sortIndex (these are mx_internal) which are used to draw the caret in the placeSortArrow method.
In my case I had results coming back from a server on each click so I had to extend DataGrid and override the headerReleaseHandler method. In there I stopped the default sort from happening and saved the column to be sorted off, when the results were returned from the search I reset the search critera in the sort attribute on the new collection called refresh and all was well.
But like peterd said, there is probably another way :).
Hi ,
Thanks for the post.
Saved me some time.
Your posts always help me with the right kind of stuff.
Anil
How do you do this with an HTTPService? I am using SQL and tried to convert it to an ArrayCollection, but no luck.
Hello Jason,
Could you tell me how you override headerReleaseHandler? I can’t do this… I have an exception “1020: Method marked override must override another method”
Please…
interesting, seems to imply that the data model is actually being sorted, not the view itself. which would mean you can’t use the same data model to back two different tables (since then sorting one would sort the other)??
btw, I just noticed in my sample app that when the data provider value changes, my table updates automatically but it also loses whatever sort happened to be set on it. is this a ‘bug’?
How do I do the first part but with a XMLList and not an array? Could you please give one example? Pretty please :)
@bsides,
How about this?
Peter
If you just want to display arrows without sorting the model, you can extend the datagrid class and add these 2 methods :
public function set sortIndex(index:uint):void { mx_internal::sortIndex = index; } // Column index
public function set sortDirection(direction:String):void { mx_internal::sortDirection = direction; } //ASC or DESC
you don’t need to refresh the dataprovider…
Hope that helps
Alex
@Alexandre Croiseaux
thanks!
i needed to invalidateDisplayList() on the grid afterwards tough
I have an interesting challenge with regard to sort arrows. I would like to not show them in order to preserve available label real estate. I have attempting this by setting sortArrowSkin to various things but with no luck. Might you be able to offer me any advise?
@Colin,
You should be able to set the sortArrowSkin to null, although it would appear that it makes the column unsortable (that may be a bug):
Peter
Or you could set the
sortArrowSkinstyle via an external .CSS file or <Style> block, as seen in the following example:Peter
And the workaround for the null sort arrow skin not performing a sort is to set the
sortArrowSkinstyle to something like ProgrammaticSkin instead:I’ll file a bug at http://bugs.adobe.com/flex/ later today and document the workaround and then post the bug number here for anybody interested.
Peter
Bug filed; http://bugs.adobe.com/jira/browse/SDK-25679
When I tested in Flex 3.5, I got a runtime error. I don’t remember seeing that at home, so I’ll double check my home config later.
Peter
This solution works perfectly. Thanks again and thank you for this blog; a fantastic resource.
Hi,
Another way to prevent the sort arrow from appearing is to override placeSortArrow to do nothing:
override protected function placeSortArrow():void{}
- Rob
@Rob,
Good tip, thanks!
Peter
We actually have a grid that solves the issue of placing the intial sort arrow as required by the original poster. This is available at http://www.flexicious.com. We also have a solution for the advanced datagrid, where you can programatically add multiple sorts and it will draw the arrows appropriately.
Very nice how this person solved it:
http://interactive-squared.co.uk/index.php/2009/10/12/programmatically-getting-datagrid-to-sort/
Peter i used the headerrelease function to sort the datagrid, the code is:
arrcoll is my dataprovider, but when sort the ArrayCollection lose the arrow ASC/DSC.
private var clickedColumn:String;
private function dataGrid_headerRelease(evt:DataGridEvent):void {
var dgrid:DataGrid = DataGrid(evt.currentTarget);
var column:DataGridColumn = dgrid.columns[evt.columnIndex];
var tempField:Object = column.dataField;
clickedColumn = tempField.toString();
dgPacientes.dataProvider = arrCol;
}
i need help.
bye.
@Paul,
Not sure where your sorting code is, but I’d guess that you’re losing the sort arrow because you are resetting the data provider each time the header is clicked.
Peter
sorry about my english… This code has helped me, but i can’t get sort data from down to up, i’m using flash builder 4 and sdk 4. Any help would be very appreciated.
solved: arrColl.lastResult.sort.fields = [new SortField("idx", true)];. Easy XD.
Hi All,
I am working on sortarrow skin for past 4 days and its really frustrating.
I am trying to show a disabled sort arrow skin on all columns when datagrid loads initially.When a user clicks on particullar column the disabled skin should be removed and changed to a different skin.I extended grid and override updatelist,headerrelease but nothing worked as planned.I am really hopping that someone can help me with it.I am trying to achieve this for past few days but had many prioblems.
Thanks ……..
Sort and SortField are flawed in the standard Adobe grid. For one thing, they do not respect any custom SortCompareFunctions you may have set on the grid, and while the arrows will appear if you have ONE field set, it will not appear if you have two set.
I found that most of the requirements in the original posting can be better addressed without extending any classes simply by dispatching a headerRelease Event.
This actually works FAR better than using sortFields because not only does it cause the arrow to appear correctly, it will also respect any custom sortCompareFunction/s on the DataGridColumns, which the basic Sort/SortField method does not do.
/**
* Whenever data or external sort criteria change, call this method. It will
* resort the pending list by simulating a mouseclick (headRelease event), triggering
* a sortColumn() call.
*
* The normal method of sorting (creating a SortField) does not respect the sortCompareFunction
* rules and does not pop up the little arrow on the column(s) being sorted; this does.
* */
private function setDefaultPendingSort():void {
// Adobe's "textbook" way to sort columns doesn't respect custom column sorting,
// and will not display the arrow when sorting on multiple columns:
//model.sampleList.sort = new Sort();
//model.sampleList.sort.fields = [new SortField("emp_name", true,false,true), new SortField("emp_id",true,false,true)];
//model.sampleList.refresh();
// The MUCH better way simulates a mouseclick on the header...
var defaultColumn:String = "emp_name"; //"accessionNum";
var col:DataGridColumn = getColumnByDataField(dgPendingSamples, defaultColumn);
col.sortDescending = false;
var dgEvent:DataGridEvent = new DataGridEvent("headerRelease");
dgEvent.dataField = defaultColumn;
dgEvent.columnIndex = getColumnIndexByDataField(dgPendingSamples, defaultColumn);
dgEvent.rowIndex = -1;
dgPendingSamples.dispatchEvent(dgEvent);
}
/**
* Returns the column based on the column's data field. Returns the first column found that
* uses the specified dataField, or -1 if none found.
* */
private function getColumnIndexByDataField(dg:DataGrid, dfld:String):int {
for (var i:uint = 0; i < dg.columnCount; i++) {
var col:DataGridColumn = dg.columns[i];
if(col.dataField == dfld) {
return i;
}
}
return -1;
}
/**
* Returns the column based on the header text, allowing
* columns to be rearranged without fucking up column dependencies.
* Returns null if none match.
* */
private function getColumnByDataField(dg:DataGrid, dfld:String):DataGridColumn {
for (var i:uint = 0; i < dg.columnCount; i++) {
var col:DataGridColumn = dg.columns[i];
if(col.dataField == dfld) {
return col;
}
}
return null;
}
hello peter
in my example I have two datagrids, the first “cltdgg” is sorting and arrow appears in the columns. While nothing in the second. Is there a link to the AsyncListView?
Thank you for your help :)
Flex4, FlashBuilder 4.5 for Php
here is the code exemple :
private var dataProvider : ArrayCollection = new ArrayCollection(
[{price:"20",location:"india"},
{price:"5",location:"india"},
{price:"40",location:"india"},
{price:"20",location:"germeny"},
{price:"20",location:"spain"},
{price:"10",location:"usa"},
{price:"30",location:"Italy"}]);
protected function cltDg_creationCompleteHandler(event:FlexEvent):void {
getClientsResult.token = serviceClients.getclients();
}
If you have multiple columns to sort and you want the sort arrow to show up, extend datagrid and grab these values (assuming they were set already), such as after a headerRelease
var curSortDirection:String = mx_internal::sortDirection;
var curSortIndex:int = mx_internal::sortIndex;
Then after creating the sorts you want and refreshing dataProvider, set the mx_internal values back to what they were and all will be well.