flexgeek

Tutorial: Using same itemRenderer for multiple columns

Posted on: May 30, 2007

Sample this case: You have 7 columns in your datagrid, each of which need an itemRenderer to display some conditional formatting by changing the background color based on the data belonging to that particular column. Ex – a value range of 1 – 10 will have colors varying from pale pink to red in column 1, but te same value range will display pale green to bright green in column 2 and similarly for the rest of the columns.

How will you solve this?

Solution 1: Write an itemRenderer for each column and code the logic for formatting in the indvidual renderers.

Solution 2: Write a single itemRenderer for all the columns which will achieve conditional formatting based on the columnIndex.

Practically, both this solutions can bee used but for many simple formatting cases, writing a single itemRenderer will be a much more robust solution. The example that I am illustrating below adopts the methodology mentioned in solution 2.In this simple example, I have used an itemRenderer called customItemRenderer to display different data across different columns in a DataGrid. Based on the columnIndex , the datagrid will display 3 different smiley’s in its 3 columns.

Please note that this kind of approach will be strictly tied to column indices and hence a situation where you have to use column dragging and reordering this methodology will not be useful. In the example, I have set draggableColumns=false.

Let us look in to the main application code:

<?xml version=”1.0″ encoding=”utf-8″?>
<mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml&#8221; layout=”absolute” creationComplete=”populateData()” viewSourceURL=”srcview/index.html”>
<mx:Script>
<![CDATA[
//DataGrid event, fired when the itemEditing is performed
import mx.events.DataGridEvent;
//Used for populating the datagrid
import mx.collections.ArrayCollection;
//Used to display the Alert
import mx.controls.Alert;
//ArrayCollection that will hold the data
[Bindable]private var arr:ArrayCollection
private function populateData():void
{

//Create an arraycollection
arr = new ArrayCollection()
//Loop to create 10 records
for(var i:int=0;i<10;i++)
{

//Create an object to insert into the array collection
var obj:Object = {col1:i, col2:i,col3:i}
//Add the object to array collection
arr.addItem(obj)
}

}

]]>
</mx:Script>
<!– DataGrid Instance, dataProvider is bound to ‘arr’- the arraycollection. –>
<mx:DataGrid draggableColumns=”false” variableRowHeight=”true” wordWrap=”true” editable=”true” id=”datagrid” x=”56″ y=”104″ height=”176″ width=”317″ dataProvider=”{arr}” themeColor=”#CECECE”>
<mx:columns>
<mx:DataGridColumn headerText=”Column 1″ dataField=”col1″ itemRenderer=”customItemRenderer”/>
<mx:DataGridColumn headerText=”Column 2″ dataField=”col2″ itemRenderer=”customItemRenderer”/>
<mx:DataGridColumn headerText=”Column 3″ dataField=”col3″ itemRenderer=”customItemRenderer”/>

</mx:columns>
</mx:DataGrid>

</mx:Application>

There are 3 datagrid columns and each of them have the same itemRenderer assigned to them.
Well , that was fairly straight forward. Now lets take a look at the itemRenderer code. Thats where most of the action is 🙂

<?xml version=”1.0″ encoding=”utf-8″?>
<mx:Canvas xmlns:mx=”http://www.adobe.com/2006/mxml&#8221; width=”182″ height=”30″ implements=”mx.controls.listClasses.IDropInListItemRenderer” horizontalScrollPolicy=”off”>
<mx:Script>
<![CDATA[
import mx.controls.listClasses.BaseListData;
import mx.controls.dataGridClasses.DataGridListData;
protected var _listData:DataGridListData;
override public function set data(value:Object):void
{
setIt(value);
}
public function get listData():BaseListData
{
return _listData;
}
public function set listData(value:BaseListData):void
{
_listData = DataGridListData(value);
invalidateProperties();
}
private function setIt(value:Object):void
{
if(value && _listData)
{
if(_listData.columnIndex == 0)
{
img.source=”a.gif”
}
else if(_listData.columnIndex == 1)
{
img.source=”b.gif”
}
else
{
img.source=”c.gif”
}
}
}

]]>
</mx:Script>
<mx:Image x=”10″ y=”6″ width=”20″ height=”20″ id=”img”/>
</mx:Canvas>

Look at the first line of the itemRenderer code. for getting access to the _listData property we have to implement the interface IDropInListItemRenderer, which has two methods.

public function get listData():BaseListData
{
return _listData;
}
public function set listData(value:BaseListData):void
{
_listData = DataGridListData(value);
invalidateProperties();
}

The _listData object holds the property columnIndex, which tells you which column does the itemRenderer belong to. Once you have the columnIndex, write your conditional logic to display corresponding data. In this case I am setting a smiley to the image control in the itemRenderer based on the columnIndex.

This can be extended to any level of conditional formatting too 🙂

View sample application | Download source

10 Responses to "Tutorial: Using same itemRenderer for multiple columns"

This is perfect. I’ve been wondering how to do this for some time now.
Thanks a lot!!

The only problem is that selecting an item does not highlight that row. Implementing IdropInListItemRenderer causes this problem. Do you have a work around for this?. Thanks. RR

Thanks for posting this. I haven’t tried it yet but at least it’s nice to see that it’s not trivial.

very interesting.
i’m adding in RSS Reader

Thanks. The IDropInListItemRenderer interface was exactly what I needed for being able to do a drag-and-drop from outside of an AIR app into the cells of a grid. This allows me to capture which cell is being dropped on.

this’s cool. I haven’t tried but it’s useful for my current project.

sound great, but i need to know how to put two diferent item renderers
in one column.

is it possible??

thanks

Thanks for the tutorial, it’s what I was looking for, but I get an error when I click on a cell:

TypeError: Error #1009: Cannot access a property or method of a null object reference.
at mx.controls::DataGrid/mouseDownHandler()

Great info, I had a large list of simple true /false and didn’t want to tie myself to column index.
Instead of _listData. columnIndex I used _listData.dataField.

You can then use that in any comparison
value[_listData.dataField]

For my simple log list of true / false I had a check mark embedded graphic and checked for true

override public function set data( value:Object ) : void {
super.data = value;
if (value && _listData) {
if (data[_listData.dataField]) {
thumbNailImage.source = checkMarkIcon;
}

}

}

wow, great code! saved hours of work! cheers!

Leave a comment

Categories