Thursday, July 26, 2007

I'm back on the flex bandwagon!

Now I'm working for a company in San Diego, and I've made a very beautiful reporting engine for them. As I'm going through my code wanting to make it even easier to work with and make future reports, I came across the DataGridColumn itemRenderer - which imo was implemented incorrectly by adobe.
The problem: You want to pass the field to render in and reuse the same renderer many times, but theres no way to do that!

So, I found a few solutions online, but modified them slightly to require no actionscript coding within the UI component itself (a practice of mine I'm trying my damnedest to stick to, as it forces me to write simple reusable classes, though not always clean and easy to understand the internals of).

The result I aimed for was being able to do this:

<itemRenderers:MoneyRenderer field="roomRevenue" datagridcolumn="{this.roomRevenueDataGridColumn}"/>

roomRevenueDataGridColumn is the id of a datagridcolumn in some datagrid in the report, and "roomRevenue" is the XML field we want to be given a dollar sign and comma separators with two decimal spaces.

And here is MoneyRenderer.as file that enables this:

package com.somecompany.reports.itemRenderers
{
import mx.core.IFactory;
import mx.controls.dataGridClasses.DataGridColumn;
/*
Class used for converting a number to a dollar preceded, comma delimited, 2 decimal formatted string.
Sample Usage:
<itemrenderers:moneyrenderer id="theMoneyRenderer" field="roomRevenue" datagridcolumn="{this.roomRevenueDataGridColumn}"/>
*/
public class MoneyRenderer implements mx.core.IFactory
{
public var field:String;
public function set dataGridColumn(dgc:DataGridColumn):void {
dgc.itemRenderer=this;
}
public function newInstance():* {
return new MoneyClass(field);
}
}
}
import mx.controls.Text;
import mx.formatters.CurrencyFormatter;

class MoneyClass extends mx.controls.Text
{
public var field:String;
public function MoneyClass(f:String):void {
field=f;
}
override public function set data(value:Object):void {
super.data = value;

var cf:CurrencyFormatter = new CurrencyFormatter;
cf.currencySymbol = "$";
cf.precision = 2;

if (value != null) {
this.text = cf.format(value[field]);
}
super.invalidateDisplayList();
}
}