Render Me This

I was recently working with item renderers on a project and wanted to post an example of using an ActionScript (class) based item renderer and compare it with an MXML version.

It is nice to have the option to choose either, but I like the control an ActionScript class gives the coder and it tends to yield a more lightweight approach than MXML.

My first code block below is the AS class approach. The renderer simply applies a currency format to a field of numbers in a data grid. The second is utilizing the MXML approach. As you can see they yield the same results.

Notice how both approaches override the data setter for the label class they extend. Also see how how listData is utilized to associate the drop-in item renderer with the data from the list control.

With this rather basic example you can see how any control can be displayed via MXML or ActionScript and drawn out i.e. rendered in a list based class.

I have attached a zipped project that displays 2 grids using both renderers. I hope this helps you better understand the power of item renders and what you can do with them.

********* UPDATE: ************

I forgot to mention in this blog that a custom label could be applied via the DataGridColumn labelFunction to get the same effect in assigning a currency symbol.

Please see an example of the code below.

<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

<mx:Script>
<![CDATA[
import mx.controls.dataGridClasses.DataGridColumn;
import mx.collections.ArrayCollection;

[Bindable]
private var cars:ArrayCollection = new ArrayCollection( [
{ Make: "Infiniti", Model: "G37", Year:2008, Cost: 44081 },
{ Make: "Lexus", Model: "IS 350", Year:2008, Cost: 45205 },
{ Make: "BMW", Model: "3 Series", Year:2008, Cost: 49100 } ]);

// this function is call via the DataGridColumn labelFunction // and it utilizes the CurrencyFormatter below private function currencyLabelFunction(item:Object, column:DataGridColumn):String {
return cf.format(item["Cost"]);
}      

]]>
</mx:Script>

<mx:CurrencyFormatter id="cf" precision="2"/>

<mx:Panel title="Label Function Example" layout="horizontal">

<mx:DataGrid dataProvider="{cars}" id="labelFuncCars">
      <mx:columns>
            <mx:DataGridColumn headerText="Make" dataField="Make" width="60" />
            <mx:DataGridColumn headerText="Model" dataField="Model" width="60" />
            <mx:DataGridColumn headerText="Year" dataField="Year" width="60" />
            <mx:DataGridColumn headerText="Cost" dataField="Cost" width="100" textAlign="right" labelFunction="currencyLabelFunction" />
      </mx:columns>
   </mx:DataGrid>

</mx:Panel>
</mx:Application>

CurrencyRendererAS Class

package renderers
{
import mx.controls.Label;
import mx.controls.dataGridClasses.DataGridListData;
import mx.formatters.CurrencyFormatter;

public class CurrencyRendererAS extends Label
{
private var cf : CurrencyFormatter = new CurrencyFormatter();

public function CurrencyRendererAS()
{
super();

// set precision for formatter cf.precision = 2;
}

// Override the set method for the data property. override public function set data(value:Object):void {
super.data = value;

if (value != null)
{
this.text = cf.format(value[DataGridListData(this.listData).dataField]);
this.setStyle("textAlign","right");
}

super.invalidateDisplayList();
}
}
}

CurrencyRendererMXML MXML

<?xml version="1.0" encoding="utf-8"?>

<mx:Label xmlns:mx="http://www.adobe.com/2006/mxml"
width="100%">

   <mx:CurrencyFormatter id="cf" precision="2"/>
   
<mx:Script>
<![CDATA[
import mx.controls.Label;
import mx.controls.dataGridClasses.DataGridListData;
import mx.formatters.CurrencyFormatter;

      override public function set data(value:Object):void {
super.data = value;

if (value != null)
{
this.text = cf.format(value[DataGridListData(this.listData).dataField]);
this.setStyle("textAlign","right");
}

super.invalidateDisplayList();
}
]]>
</mx:Script>
</mx:Label>

AS Approach Output

MXML Approach Output

Label Function Output

Comments
Hardly a fair comparison... the MXML is essentially the same as the AS, a proper MXML version would be something like this (I hope the XML will be rendered correctly):

<Label xmlns="...">
<text>{cf.format(value[DataGridListData(this.listData).dataField])}</text>
<textAlign>right</textAlign>

<CurrencyFormatter id="cf" precision="2"/>
</Label>

Ffive lines in total, which also shows the benefit of using MXML: brevity.
# Posted By Theo | 1/10/08 4:45 AM
@Theo

Thanks for the reply but this code does not work for a few reasons.

One, you still have to import your DataGridListData. (can't get away from script here).

Secondly, value is passed via the data setter override (won't compile)

Third, if I hack it a bit and replace value with data I can get it to work, but receive compile warning due to data bindings being unable to detect dataField.
# Posted By Jeff Bouley | 1/10/08 9:21 AM
"value" should be "data", and "DataGridListData" could be replaced by "Object". Then it should work. Or you can use listData['dataField']. It should not be impossible to get around that, but it's besides the point (which was that your MXML example didn't actually do anything different from your AS example).
# Posted By Theo | 1/10/08 9:30 AM
@Theo

That was the point of the blog, (there's two ways to "skin the proverbial cat" here). Whether one chooses AS or MXML is truly preference. Per your reply I am leary of using "Object" as well because you lose your typing.

I only ask if you are going to post code here in the future that you test it out. Don't want to mislead my readers.

Thanks again for reading and good luck to you.
# Posted By Jeff Bouley | 1/10/08 10:17 AM
You can always take advantage of both (especially in more complicated renderers) by extending your MXML from your AS file - in a code behind fashion, thus allowing you to separate the majority of your logic from your view, while being able to simultaneously leverage MXML
# Posted By Eric | 1/15/08 3:29 PM
@Eric,

Thanks for the comment. A very good point indeed. You have an excellent blog. I have been fortunate enough to work on some great projects where I readily witnessed the power of writing AS classes that extended sprite or uicomponent.

Something I probably should have addressed, though I wanted to keep this blog entry simple and allow the readers imagination to take them into more advanced examples.
# Posted By Jeff Bouley | 1/16/08 10:14 PM
Hello, maybe somebody of you knows a sollution for my problem, which is one step further. I use a currency field in a datagrid, which ist editable. I have to convert the value for the dataprovider to a Number and I have to use a given currency format (european style: 1.234,56. So I didn't find a proper way of converting to a proper number - resulting in NAN values. Does anybody know how o solve this problem?!
# Posted By Niels | 4/2/08 11:16 AM

Copyright Strikefish, Inc., 2005. All rights reserved.