Formatting a Flex DataGrid control using a custom item renderer
The following example formats a column in a Flex DataGrid and uses a custom item renderer to color the text red in a cell if a price is below $0. If the item is greater than $0, the test is displayed in black. The price column is also formatted using a custom label function, which uses a CurrencyFormatter, and finally, the data grid column uses a custom sort function to properly sort numeric columns.
Full code after the jump.
<?xml version="1.0" encoding="utf-8"?> <!-- http://blog.flexexamples.com/2007/08/20/formatting-a-flex-datagrid-control-using-a-custom-item-renderer/ --> <mx:Application name="DataGridColumn_itemRenderer_test " xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" verticalAlign="middle" backgroundColor="white"> <mx:Script> <![CDATA[ import mx.controls.dataGridClasses.DataGridColumn; import mx.utils.ObjectUtil; private function price_labelFunc(item:Object, column:DataGridColumn):String { return currencyFormatter.format(item.@price); } private function price_sortCompareFunc(itemA:Object, itemB:Object):int { return ObjectUtil.numericCompare(itemA.@price, itemB.@price); } ]]> </mx:Script> <mx:XML id="itemsXML"> <items> <item name="Item 1" price="1.32" /> <item name="Item 2" price="-12.23" /> <item name="Item 3" price="4.96" /> <item name="Item 4" price="-0.94" /> </items> </mx:XML> <mx:Style> .centered { text-align: center; } </mx:Style> <mx:CurrencyFormatter id="currencyFormatter" precision="2" useNegativeSign="false" /> <mx:DataGrid id="dataGrid" dataProvider="{itemsXML.item}"> <mx:columns> <mx:DataGridColumn dataField="@name" headerText="Name:" headerStyleName="centered" /> <mx:DataGridColumn dataField="@price" headerText="Price:" textAlign="right" headerStyleName="centered" labelFunction="price_labelFunc" sortCompareFunction="price_sortCompareFunc" itemRenderer="PriceLabel" /> </mx:columns> </mx:DataGrid> </mx:Application>
And the custom item renderer, PriceLabel.as, is as follows:
/** http://blog.flexexamples.com/2007/08/20/formatting-a-flex-datagrid-control-using-a-custom-item-renderer/ */ package { import mx.controls.Label; import mx.controls.listClasses.*; public class PriceLabel extends Label { private const POSITIVE_COLOR:uint = 0x000000; // Black private const NEGATIVE_COLOR:uint = 0xFF0000; // Red override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void { super.updateDisplayList(unscaledWidth, unscaledHeight); /* Set the font color based on the item price. */ setStyle("color", (parseFloat(data.@price) <= 0) ? NEGATIVE_COLOR : POSITIVE_COLOR); } } }
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.
48 Responses to Formatting a Flex DataGrid control using a custom item renderer
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


Hi,
Thanks a lot man !
Hi Peter,
Thanks for the example! :)
Do you know how to create an item renderer in a datagrid column that creates different components based on the data?
For example,
column 1…….column 2
————————-
item 1………[checkbox]
item 2………[checkbox]
item 3………[combobox]
item 4………[textinput]
item 5………[textinput]
data:
array = [{label:'item 1',type:'checkbox'},etc]
When I scroll or sort the headers everything screws up.
How do I center align a checkbox inside a datagrid? It always aligns left…Please help.
Richie,
I’m not sure, but check out Alex Harui’s excellent blog entry, “More Thinking About Item Renderers”, which has demo and full source code.
Peter
Could you say me build number of Flex complier. I got another behavior of your example. Price column and cell have the same align – “right”.
My build number: Version 2.0.1 build 155542.
Thanx.
sinnus,
All of the examples in this blog were built with various beta/nightly builds of the Flex 3 SDK.
Peter
@Ritchie,
I’ve centered a checkbox in a datagrid column before by adding an HBox around it and using horizontalAlign=”center”
Hey Now,
Nice post it was helpful to me.
Thx 4 the info,
Catto
An improvement to the label function might be to change the return currencyFormatter.format(item.@price); t0 return currencyFormatter.format(item[column.dataField]);
This should make the label function usable on any column that can be formatted as currency rather than hardcoding in the column field.
Hi Peter, how can I do to change the background of entire line, based in some information in the fields? Thanks.
@judah (6 months later),
i think you need to override the set data accessor – the same instances of the renderer get reused, you’ll need to change the contents of the view hierarchy when the data changes,
Flex newbie… Is there a way to make this package more generic so the colomn nmae doesn’t have to be embedded in the package? This way any column that needed this formating “itemRenderer” could use this package.
Thanks for all of your examples!!
Greg C,
Try something like this:
Peter
Hi , i was wondering where the listData object comes from?
Thanks in advance for your help
Thanks Peter. Worked great!
Peter,
I am trying to apply your above example to similar code for another use of a datagrid itemRenderer. So I was wondering if you could point me in the right direction if I wanted the value of an external Control to affect the threshold point of the values that are colored.
So if I had an hslider it could be used to dynamically change the value of the cut-off point of the colored items in that column of the datagrid.
So basically instead of:
setStyle("color", (data[dField] <= 0) ? NEGATIVE_COLOR : POSITIVE_COLOR);it would be:
setStyle("color", (data[dField] <= X) ? NEGATIVE _COLOR : POSITIVE _COLOR);X being the value that would be represented by the position of the hslider.
Does this make sense?
Since I am new to this whole package/class thing I am not sure how to access that external value inside of the package that is being called by the itemRenderer of a grid column.
Thanks again!
Peter, Once again sorry for the double post… Any thoughts regarding how I can go about passing a dynamic value from a control into this package? I have tried a couple things and none of which seem to work.
Thanks,
Greg C
Greg C,
Probably not the best solution, but you could try using
Application.application.slider.value. I’m not sure how well it would work since the itemRenderers wouldn’t necessarily be updated when the slider changes.Peter
Some more great info, thanks for the tips.
Note that a similar solution (for background-color) is posted by jlafferty at:
http://butterfliesandbugs.wordpress.com/2007/07/11/using-an-itemrenderer-to-change-the-background-of-a-datagrid-cell/
Hi guys,
In this example, how can be sorted the price column as a number?
Any ideas?
Janet
janet,
The price column is sorting as numbers, isn’t it?
Peter
Nope, when the prices are loaded you get ($1.32, $12.23, $4.96, $0.94), if you sort the price column you get ($12.23, $0.94, $1.32, $4.96) instead of ($12.23, $4.96, $1.32, $0.94), and if you sort again to get the numbers from descendant to ascendant you have($4.96, $1.32, $0.95, $12.23) instead of ($0.95, $1.32, $4.96, $12.23)…
janet,
Interesting. I see the same default sort as you (1.32, -12.23, 4.96, -0.94) — the items are unsorted and appear in the same order they were specified in the data provider.
If I sort by price (descending), I get the following: -12.23, -0.94, 1.32, 4.96 (or Item 2, Item 4, Item 1, Item 3). This sort is correct since the biggest negative values are first and the biggest positive values are last.
If I sort by price (ascending), I get the following: 4.96, 1.32, -0.94, -12.23 (or Item 3, Item 1, Item 4, Item 2). This sort is correct since the biggest positive values are first and the biggest negative values are last.
Actually, are you sure your numbers are right? 0.94 and 12.23 are both negative numbers. So I wouldn’t expect the price column to sort as 12.23, 4.96, 1.32, 0.94 since both 0.94 and 12.23 are negative numbers in the data provider. I’d expect 4.96, 1.32, -0.94, -12.23.
Peter
hi,
i have developed a similar example. the difference is that my item renderer is a linkbutton extend class. The override function is the next:
my problem is when i sort a column. When i click the column header, the data rows are changed but not sorted… but i move the mouse cursor over the rows… magically… the data in the columns are going to appearing sorted.
any idea?
thanks, congratulations, it´s a great website
Hello,
Thank for this very interesting example.
If a change the source with an arraycollection, what kind of modifications i must do in the PriceLabel.as field ?
Thanks
Best Regards
Pierre,
In PriceLabel.as, it looks like I hard-coded the column data field (
data.@price) into the item renderer. Of course, you could create a new subclass for each different data field (CostLabel.as, etc.), but that would probably not be the best approach.I think the better approach would be to look at my coworker Alex Harui’s solution to this, as he is ridiculously smarter than I am: “Thinking About Item Renderers”. Specifically, I was reading the Text Color and Styles in Item Renderers section. He shows how you can extend both the DataGridColumn and DataGridItemRenderer classes, and create a custom
stylesFunction()method which evaluates the data in a column without hard-coding specific column names.Peter
Can an ItemEditor dispatch their own events? If so, how do you set an event listener to capture the event?
I’m trying to use similar code but have the logic based on the value of an attribute “D” in my xml data but I cannot figure out for the life of me how to access the attribute in the .as file for the current column (I’m using the renderer for multiple columns). My XML looks something like this:
using data..@D gives all D values for the current cols node (i.e. “12″). Can anyone advise?
Thanks!
Sussed it!
I have try your example.Very useful.Thanks lots. I still have one question and hope you can help. Now I have 2 string, lets say AAA and BBB which I want to change their color out of many data. I try to use :
but it only change the color of BBB.
So what should I do to change both field?
thanks
Hi,
Very nice blog … Is there any way to change the text color of the entire row of a datagrid based on data with out creating a itemrenderer for each column. I have around 10 columns, and want to change the color of text to red or green based on some data.
Thanks,
Shreyas
Is there any concern of this method being a performance hit? I put a trace statement in my updateDisplayList() in my custom component while I was getting things going. I noticed that if I had 10 items, on load i got 20-30 traces. If I move my mouse over I get more traces. Same with a select. I understand why this happens, but is there not a way to set it and forget it? Does the DG loose the settings each time it redraws?? I am still sort of amazed that there isn’t just a property to set for a row color.
Hi peterd
Instead of comparing the data value with 0, If i want to do comparison of two column value and set the row value red if column1 value is less than column2 value then how can i do?
@Niladri,
Try something like this:
And the custom item renderer, PriceLabel.as, is as follows:
Peter
Thanks a lot Peter.
Peter, I have one doubt.I’m allocating data field for the data grid column dynamically. So some time it will not have data field as col1,may be some time it will have column field as col3 or col4.So my question is instead of referring data field in PriceLabel.as can I use the column id of those two column in PriceLabel.as
I would like to know if I could pass some objects to the constructor of the customItemRender class because I wasnt able to do it, the compiler throws an error. I attach my code below:
customItemRender class:
package core {
import mx.containers.VBox;
import mx.controls.TextInput;
public class customItemRender extends VBox {
public function customItemRender(_TextInput:TextInput, _TextInput2:TextInput){
//TODO: implement function
super.addChild(_TextInput);
super.addChild(_TextInput2);
}
}
}
Actionscript code for creating an AdvancedDataGrid itemRender:
AdvancedDataGridColumn.itemRenderer = new ClassFactory(customItemRender(_TextInput1,_TextInput2));
Thanks in advance for your help,
Regards Javier
Thanks for the awesome example, I think the fact that you’re still getting comments on a two year old post speaks to the usefulness of it.
I have multiple columns that I need to run through a label function, can you think of a quick way to make the label function re-usable?
TIA,
~S
Never mind, I got it:
private function cur_labelFunc(item:Object, column:DataGridColumn):String { return cF.format(item[column.dataField]); }See any problems with that?
Thanks again,
~S
Great example, yet again you saved the day for me.
This is a good example but ItemRenderer works only with small amount of data. If you have a huge advanceddatagrid like say 50 columns and 1500 rows and you try to use an itemRenderer on it , your application will be really slow when you try to scroll horizontally or vertically. I had a similar advanced datagrid where I used itemrenderer and setStyle to show +ve numbers in blue and -ve numbers in red and it runs very slow.Let me know if you have a better solution to this problem or make it run faster. Try it when the data is getting updated every 10 seconds
Thanks for your example and the nice comments there.
I am facing a problem while trying to change the background. I am trying to change the background of specific cells that pass conditions. Like here I am testing if I have start Letter then I am testing if it delivered to the group leader or not by testing the dates of Start Letter and system date. Then if it is already sent to group leader, check if the group leader approved it or not. If not check the difference between the dates of the system date and the sent to group leader date. If the result is greater than 15 and less than 30, color that cell with red color. The other cells that are not used like manager will be in gray.
If you could help me with this problem.
My code is the following:
package com.aramco.easd.ats.vo
{
import flash.display.Graphics;
import mx.controls.DataGrid;
import mx.controls.Label;
import mx.controls.dataGridClasses.*;
import mx.utils.StringUtil;
[Style(name="backgroundColor", type="uint", format="Color", inherit="no")]
public class BackgroundColor extends Label
{
public var g:Graphics;
public function BackgroundColor()
{
super();
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth, unscaledHeight);
g = graphics;
g.clear();
var grid1:DataGrid = DataGrid(DataGridListData(listData).owner);
g = graphics;
g.clear();
unscaledWidth = this.unscaledWidth;
unscaledHeight = this.unscaledHeight;
if (grid1.isItemSelected(data) || grid1.isItemHighlighted(data))
return;
checkStageLevel();
} // end of override function
public function checkStageLevel():void
{
var systdate:Date = new Date;
// is the letter send or not to group leader
if ((data.tmldSentDt == null || StringUtil.trim(data.tmldSentDt) == “”) && (data.taskStaDt != null || StringUtil.trim(data.taskStaDt) != “”))
{
checkDurationForStage(systdate, convertMyDate(data.taskStaDt));
}// is the letter approved by group leader or waiting him/her to approve it
if ((data.tmldApvDt == null || StringUtil.trim(data.tmldApvDt) == “”) && (data.tmldSentDt != null || StringUtil.trim(data.tmldSentDt) != “”))
{
checkDurationForStage(systdate, convertMyDate(data.tmldSentDt));
}// is the letter approved by division head or waiting him/her to approve it
if(data.ltrdesc == “Staking” || data.ltrdesc == ” Survey)
{
if ((data. mgraSentDt == data. mgraSentDt || StringUtil.trim(data.dvhwSentDt) == “”) && (data[DataGridListData(listData).dataField] == “mgraSentDt” || StringUtil.trim(data[DataGridListData(listData).dataField]) == “mgraSentDt”))
{
g.beginFill(0xA9A9A9);
g.drawRect(0, 0, unscaledWidth, unscaledHeight);
g.endFill();
}
if ((data. mgraApvDt == null || StringUtil.trim(data. MgraApvDt) == “”) && (data[DataGridListData(listData).dataField] == “mgraApvDt” || StringUtil.trim(data[DataGridListData(listData).dataField]) == “mgraApvDt”))
{
g.beginFill(0xA9A9A9);
g.drawRect(0, 0, unscaledWidth, unscaledHeight);
g.endFill();
}
}
public function convertMyDate(strToCheck:String):Date {
var uryear:String;
var urmonth:String;
var urday:String;
var newDate:Date;
uryear = strToCheck;
if (uryear != null)
uryear = uryear.substr(uryear.length – 4, 4);
urmonth = strToCheck;
if (urmonth != null)
urmonth = urmonth.substr(0, urmonth.indexOf(“/”));
urday = strToCheck; urday = urday.substr(0, urday.length – 5);
if (urday != null)
urday = urday.substr(3, urday.indexOf(“/”)+1);
newDate = new Date(Number(uryear),Number(urmonth)-1,Number(urday));
return(newDate);
}
public function checkDurationForStage(systdate:Date, VariableDate:Date):void
{
var ResultSysdate_VariableDate:Number = fromDates(VariableDate,systdate);
if ( 15 < ResultSysdate_VariableDate && ResultSysdate_VariableDate <= 30 && data[DataGridListData(listData).dataField] == data[DataGridListData(listData).dataField] )
{
g.beginFill(0xFF1234);
g.drawRect(0, 0, unscaledWidth, unscaledHeight);
g.endFill();
}
else if ( 30 < ResultSysdate_VariableDate && ResultSysdate_VariableDate <= 50 && data[DataGridListData(listData).dataField] == data[DataGridListData(listData).dataField] )
{
g.beginFill(0xFF1111);
g.drawRect(0, 0, unscaledWidth, unscaledHeight);
g.endFill();
}
}
public static function fromDates(start:Date, end:Date):Number
{
return Math.ceil((end.time – start.time)/MILLISECONDS_IN_DAY);
} // end of fromDates function
Thanks a lot,
Helped great .
This is my Dictionary for flex.
:)
Regards,
Sankara narayanan Ekambaranathan.
Hi,
I have a problem with a data grid.
Rows in my data grid display data with line breaks so if a text content is composed by 3 lines my row height expand in order to display all content.
The problem is that the height of rows from what I see depends form the first row height but in my case sometimes first row has just one line and the third has 3 lines (but it’s formatted as the first with one line height).
Hope you understand…
Thanks.
perfect solution
Hi ,
I have a AdvancedDatagrid having a dataprovider. In one of the column there is a dropdownList (rendered) having a different data provider. On change of the dropdownlist i want to change the labels of one of the columns of Grid .
how can this be done ?
can you please reply ?
Thanks
Thanks, man. Much appreciated.