前回までで「動的に1000単位とかに切り替えられる仕組み」は完結。
ただ、「いちいちそれ用に作ってあげないといけない」という課題があった。
「それ用に」と言っているのは、たとえば同じような話をListコンポーネントのlabelFunctionにやってあげたりとか、あるいはLabelコンポーネントのtextプロパティにこれを使おうとしても、format関数のシグネチャがDataGrid専用になってるので使い回しが利かない、ということ。
というわけで、これを解決すべく、前回までのVariableCurrencyFormatterのformat関数のシグネチャを変えて対応できるようにしてみようかと。
このVariableCurrencyFormatterの使われそうなところを考えてみると、上記のとおりDataGridとListとLabelがあるので、それぞれどういう感じか考えてみる。
まず、DataGridは今までのとおり、
public function format(item:Object, column:DataGridColumn):String
のシグネチャでOK。
Listは、
public function format(item:Object):String
なんだけど、item はその行が表示対象とするオブジェト、まぁ大抵はいわゆるDTOってやつが来るんだけど、どのプロパティを表示するかを渡してあげないとまずい。
ListコンポーネントにはlabelFieldっていうのがあって、Listの場合はそれで指定することになるので、同じように外部から与えられるようにすればいいでしょう。
ていうか、listっていうListコンポーネントがあったとしたら、
<formatters:VariableCurrencyFormatter labelField="{list.labelField}" />
ってなっているのがわかりやすい。
Labelの場合、使い方としては、
<mx:Label text="{formatter.format(hoge)}" />
という感じだろうから、引数として1個のObjectを取ってStringを返すので十分。
シグネチャが違うのだけれど、ActionScriptだと引数にデフォルト値をしておけば関数のオーバーロードみたいなのができるので、これを使えばできそう。
というわけで、
[Bindable(event="formatChanged")]
public function format(item:Object, column:DataGridColumn = null):String
{
var dat:Object = item;
if (column != null && item.hasOwnProperty(column.dataField))
{
dat = item[column.dataField];
}
else if (labelField != null && item.hasOwnProperty(labelField))
{
dat = item[labelField];
}
var curFormatter:CurrencyFormatter = new CurrencyFormatter();
return curFormatter.format(Number(dat) / unit);
}
private var _labelField:String;
[Bindable]
public function get labelField():String { return _labelField; }
public function set labelField(value:String):void
{
if (_labelField != value)
{
_labelField = value;
dispatchEvent(new Event("formatChanged"));
}
}
と書いてみた。
これでDataGrid、List(ついでにlabelFieldが動的に変わっても対応可能)、Labelのそれぞれで同じ感じに使えるようにできた。