Accessibility

Table of Contents

Understanding Flex itemRenderers — Part 2: External renderers

An MXML itemRenderer

In Part 1 you saw there was a complex itemRenderer used for a DataGrid:

<mx:DataGridColumn headerText="Title" dataField="title">
		<mx:itemRenderer>
			<mx:Component>
				<mx:HBox paddingLeft="2">
					<mx:Script>
					<![CDATA[
						override public function set data( value:Object ) : void {
							super.data = value;
							var today:Number = (new Date()).time;
							var pubDate:Number = Date.parse(data.date);
							if( pubDate > today ) setStyle("backgroundColor",0xff99ff);
							else setStyle("backgroundColor",0xffffff);
						}
					]]>

					</mx:Script>
					<mx:Image source="{data.image}" width="50" height="50" scaleContent="true" />
					<mx:Text width="100%" text="{data.title}" />
				</mx:HBox>
			</mx:Component>

		</mx:itemRenderer>
	</mx:DataGridColumn>
          

The itemRenderer is based on an HBox, contains an Image and a Text, and the background color is set according to the pubDate field of the item record. You can write this same itemRenderer as an external file using these steps:

  1. If you are using Flex Builder, create a new MXML Component file (I've named mine GridColumnSimpleRenderer, but use whatever you like) and set the root tag to be HBox. Don't worry about the size.
  2. If you are using the SDK alone, create a new MXML file (call it GridColumnSimpleRenderer.mxml) and set the root tag to be HBox.
  3. With the file open, copy everything between <mx:HBox> and </mx:HBox>, but do not copy those tags, since they are already in the file. The result should look something like this:

    <?xml version="1.0" encoding="utf-8"?>
    <mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="300">
    	<mx:Script>
    	<![CDATA[
    		override public function set data( value:Object ) : void {
    			super.data = value;
    			var today:Number = (new Date()).time;
    			var pubDate:Number = Date.parse(data.date);
    			if( pubDate > today ) setStyle("backgroundColor",0xff99ff);
    			else setStyle("backgroundColor",0xffffff);
    		}
    	]]>
    
    	</mx:Script>
    	<mx:Image source="{data.image}" width="50" height="50" scaleContent="true" />
    	<mx:Text width="100%" text="{data.title}" />
    </mx:HBox>
  4. Save the file.

Now modify the DataGridColumn definition by removing the inline itemRenderer and replacing it with this:

<mx:DataGridColumn headerText="Title" dataField="title"
itemRenderer="GridColumnSimpleRenderer">

Now run the application. You'll get a surprise. The surprise is how tall the rows are. That's because of the presence of height="300" on the itemRenderer.

Determining an itemRenderer's width and height

The List control always sets the itemRenderer's width. In this example, the explicit width="400" is ignored. You should write your itemRenderer to assume the width will change as the user changes the column or list's width.

The height is a different matter. If the list has an explicit rowHeight set, it will impose that height on each row, ignoring any height you've set on the itemRenderer. However, if you set the list's variableRowHeight property to true, then the list will seriously consider the itemRenderer's height. In this example, the height is explicitly set to 300, so each row is 300 pixels high.

To fix this, remove the explict height from the itemRenderer file and the application will work correctly.

Dynamically Changing the itemRenderer

In this example the set data() function has been overridden to examine the data and set the itemRenderer's backgroundColor. This is very common. Overriding set data() enables you to intercept the time when the data is being changed for a new row and you can you make style changes.

Common mistakes are:

  • Forgetting to call super.data = value;. This is VITAL—failure to do this will really mess up your itemRenderer.
  • Forgetting to reset the style(s) if any tests fail. It might be tempting to just set the color when the pubDate is in the future, but you have to remember that itemRenderers are recycled, and so the else statement is very necessary.