Flex Numeric Stepper with Currency
Flex's numeric stepper controls work well but will only work with numeric data so can't be used for editing currency.
Update - for a better solution look at the last code section
There's a few ways around the issues but none of the solutions are perfect.
Here's but I'd like to work;
1<?xml version="1.0" encoding="utf-8"?>
2<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
3
4 <mx:DataGrid dataProvider="{products}" editable="true">
5 <mx:columns>
6 <mx:DataGridColumn width="100" headerText="Product" dataField="description" editable="false" />
7 <mx:DataGridColumn width="60" headerText="Price" textAlign="right" dataField="price" editorDataField="text">
8 <mx:itemEditor>
9 <mx:Component>
10 <mx:NumericStepper stepSize="0.01" minimum="0.01" maximum="100" />
11 </mx:Component>
12 </mx:itemEditor>
13 <mx:itemRenderer>
14 <mx:Component>
15 <mx:HBox>
16 <mx:CurrencyFormatter id="money" precision="2" />
17 <mx:Label id="price" text="{money.format(data.price)}" />
18 </mx:HBox>
19 </mx:Component>
20 </mx:itemRenderer>
21 </mx:DataGridColumn>
22 </mx:columns>
23 </mx:DataGrid>
24
25 <mx:Script>
26 <![CDATA[
27 import mx.collections.ArrayCollection;
28
29 [Bindable] private var products:ArrayCollection = new ArrayCollection([{description:"Milk", price:1.99}, {description:"Bread", price:1.50}, {description:"Honey", price:3.99}]);
30 ]]>
31 </mx:Script>
32
33</mx:Application>
2<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
3
4 <mx:DataGrid dataProvider="{products}" editable="true">
5 <mx:columns>
6 <mx:DataGridColumn width="100" headerText="Product" dataField="description" editable="false" />
7 <mx:DataGridColumn width="60" headerText="Price" textAlign="right" dataField="price" editorDataField="text">
8 <mx:itemEditor>
9 <mx:Component>
10 <mx:NumericStepper stepSize="0.01" minimum="0.01" maximum="100" />
11 </mx:Component>
12 </mx:itemEditor>
13 <mx:itemRenderer>
14 <mx:Component>
15 <mx:HBox>
16 <mx:CurrencyFormatter id="money" precision="2" />
17 <mx:Label id="price" text="{money.format(data.price)}" />
18 </mx:HBox>
19 </mx:Component>
20 </mx:itemRenderer>
21 </mx:DataGridColumn>
22 </mx:columns>
23 </mx:DataGrid>
24
25 <mx:Script>
26 <![CDATA[
27 import mx.collections.ArrayCollection;
28
29 [Bindable] private var products:ArrayCollection = new ArrayCollection([{description:"Milk", price:1.99}, {description:"Bread", price:1.50}, {description:"Honey", price:3.99}]);
30 ]]>
31 </mx:Script>
32
33</mx:Application>
But unfortunately it doesn't. The issue is that the numeric stepper is in a vbox and the datagrid can't get at it's value.
Here's an ugly solution. The + 0.05 are to deal with rounding errors that occur.
1<?xml version="1.0" encoding="utf-8"?>
2<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
3
4 <mx:DataGrid dataProvider="{products}" editable="true">
5 <mx:columns>
6 <mx:DataGridColumn width="100" headerText="Product" dataField="description" editable="false" />
7 <mx:DataGridColumn width="60" headerText="Price" textAlign="right" editorDataField="value" dataField="price">
8 <mx:itemEditor>
9 <mx:Component>
10 <mx:NumericStepper stepSize="0.01" minimum="0.01" maximum="100" />
11 </mx:Component>
12 </mx:itemEditor>
13 <mx:itemRenderer>
14 <mx:Component>
15 <mx:Label text="${Math.floor(data.price)}.{Math.floor((data.price-Math.floor(data.price))*10+0.05)}{Math.floor((data.price*10-Math.floor(data.price*10))*10+0.05)}" />
16 </mx:Component>
17 </mx:itemRenderer>
18 </mx:DataGridColumn>
19 </mx:columns>
20 </mx:DataGrid>
21
22 <mx:Script>
23 <![CDATA[
24 import mx.collections.ArrayCollection;
25
26 [Bindable] private var products:ArrayCollection = new ArrayCollection([{description:"Milk", price:1.99}, {description:"Bread", price:1.50}, {description:"Honey", price:3.99}]);
27 ]]>
28 </mx:Script>
29
30</mx:Application>
2<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
3
4 <mx:DataGrid dataProvider="{products}" editable="true">
5 <mx:columns>
6 <mx:DataGridColumn width="100" headerText="Product" dataField="description" editable="false" />
7 <mx:DataGridColumn width="60" headerText="Price" textAlign="right" editorDataField="value" dataField="price">
8 <mx:itemEditor>
9 <mx:Component>
10 <mx:NumericStepper stepSize="0.01" minimum="0.01" maximum="100" />
11 </mx:Component>
12 </mx:itemEditor>
13 <mx:itemRenderer>
14 <mx:Component>
15 <mx:Label text="${Math.floor(data.price)}.{Math.floor((data.price-Math.floor(data.price))*10+0.05)}{Math.floor((data.price*10-Math.floor(data.price*10))*10+0.05)}" />
16 </mx:Component>
17 </mx:itemRenderer>
18 </mx:DataGridColumn>
19 </mx:columns>
20 </mx:DataGrid>
21
22 <mx:Script>
23 <![CDATA[
24 import mx.collections.ArrayCollection;
25
26 [Bindable] private var products:ArrayCollection = new ArrayCollection([{description:"Milk", price:1.99}, {description:"Bread", price:1.50}, {description:"Honey", price:3.99}]);
27 ]]>
28 </mx:Script>
29
30</mx:Application>
Here's a better solution but it needs to use an actionscript component.
1<?xml version="1.0" encoding="utf-8"?>
2<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
3
4 <mx:DataGrid dataProvider="{products}" editable="true">
5 <mx:columns>
6 <mx:DataGridColumn width="100" headerText="Product" dataField="description" editable="false" />
7 <mx:DataGridColumn width="60" headerText="Price" textAlign="right" dataField="price" editorDataField="value" itemRenderer="Money">
8 <mx:itemEditor>
9 <mx:Component>
10 <mx:NumericStepper stepSize="0.01" minimum="0.01" maximum="100" />
11 </mx:Component>
12 </mx:itemEditor>
13 </mx:DataGridColumn>
14 </mx:columns>
15 </mx:DataGrid>
16
17 <mx:Script>
18 <![CDATA[
19 import mx.collections.ArrayCollection;
20
21 [Bindable] private var products:ArrayCollection = new ArrayCollection([{description:"Milk", price:1.99}, {description:"Bread", price:1.50}, {description:"Honey", price:3.99}]);
22 ]]>
23 </mx:Script>
24
25</mx:Application>
2<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
3
4 <mx:DataGrid dataProvider="{products}" editable="true">
5 <mx:columns>
6 <mx:DataGridColumn width="100" headerText="Product" dataField="description" editable="false" />
7 <mx:DataGridColumn width="60" headerText="Price" textAlign="right" dataField="price" editorDataField="value" itemRenderer="Money">
8 <mx:itemEditor>
9 <mx:Component>
10 <mx:NumericStepper stepSize="0.01" minimum="0.01" maximum="100" />
11 </mx:Component>
12 </mx:itemEditor>
13 </mx:DataGridColumn>
14 </mx:columns>
15 </mx:DataGrid>
16
17 <mx:Script>
18 <![CDATA[
19 import mx.collections.ArrayCollection;
20
21 [Bindable] private var products:ArrayCollection = new ArrayCollection([{description:"Milk", price:1.99}, {description:"Bread", price:1.50}, {description:"Honey", price:3.99}]);
22 ]]>
23 </mx:Script>
24
25</mx:Application>
And the file Money.as:
1package {
2 import mx.controls.Text;
3 import mx.formatters.CurrencyFormatter
4
5 public class Money extends Text
6 {
7 override public function set data(value:Object):void {
8 super.data = value;
9
10 var cf:CurrencyFormatter = new CurrencyFormatter;
11 cf.currencySymbol = "$";
12 cf.precision = 2;
13
14 if (value != null) {
15 this.text = cf.format(value.price);
16 }
17 super.invalidateDisplayList();
18 }
19 }
20}
2 import mx.controls.Text;
3 import mx.formatters.CurrencyFormatter
4
5 public class Money extends Text
6 {
7 override public function set data(value:Object):void {
8 super.data = value;
9
10 var cf:CurrencyFormatter = new CurrencyFormatter;
11 cf.currencySymbol = "$";
12 cf.precision = 2;
13
14 if (value != null) {
15 this.text = cf.format(value.price);
16 }
17 super.invalidateDisplayList();
18 }
19 }
20}
While this works well there should be a more elegant solution. Anyone know how this can be done in a single MXML file?
Update
Here's a way to do it in a single MXML file.
1<?xml version="1.0" encoding="utf-8"?>
2<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
3
4 <mx:CurrencyFormatter id="cf" precision="2" />
5
6 <mx:DataGrid dataProvider="{products}" editable="true">
7 <mx:columns>
8 <mx:DataGridColumn width="100" headerText="Product" dataField="description" editable="false" />
9 <mx:DataGridColumn width="60" headerText="Price" textAlign="right" editorDataField="value" dataField="price">
10 <mx:itemEditor>
11 <mx:Component>
12 <mx:NumericStepper stepSize="0.01" minimum="0.01" maximum="100" />
13 </mx:Component>
14 </mx:itemEditor>
15 <mx:itemRenderer>
16 <mx:Component>
17 <mx:Label text="{outerDocument.cf.format(data.price)}" />
18 </mx:Component>
19 </mx:itemRenderer>
20 </mx:DataGridColumn>
21 </mx:columns>
22 </mx:DataGrid>
23
24 <mx:Script>
25 <![CDATA[
26 import mx.collections.ArrayCollection;
27
28 [Bindable] private var products:ArrayCollection = new ArrayCollection([{description:"Milk", price:1.99}, {description:"Bread", price:1.50}, {description:"Honey", price:3.99}]);
29 ]]>
30 </mx:Script>
31
32</mx:Application>
2<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
3
4 <mx:CurrencyFormatter id="cf" precision="2" />
5
6 <mx:DataGrid dataProvider="{products}" editable="true">
7 <mx:columns>
8 <mx:DataGridColumn width="100" headerText="Product" dataField="description" editable="false" />
9 <mx:DataGridColumn width="60" headerText="Price" textAlign="right" editorDataField="value" dataField="price">
10 <mx:itemEditor>
11 <mx:Component>
12 <mx:NumericStepper stepSize="0.01" minimum="0.01" maximum="100" />
13 </mx:Component>
14 </mx:itemEditor>
15 <mx:itemRenderer>
16 <mx:Component>
17 <mx:Label text="{outerDocument.cf.format(data.price)}" />
18 </mx:Component>
19 </mx:itemRenderer>
20 </mx:DataGridColumn>
21 </mx:columns>
22 </mx:DataGrid>
23
24 <mx:Script>
25 <![CDATA[
26 import mx.collections.ArrayCollection;
27
28 [Bindable] private var products:ArrayCollection = new ArrayCollection([{description:"Milk", price:1.99}, {description:"Bread", price:1.50}, {description:"Honey", price:3.99}]);
29 ]]>
30 </mx:Script>
31
32</mx:Application>
TweetBacks
Check it out - http://sethonflex.blogspot.com/2007/07/im-back-on-...