Flex AdvancedDataGridでItemRenderer(TextInput)をタブ移動しながら金額をカンマ区切りにするサンプル
Flex AdvancedDataGridで、ItemRenderer(TextInput)をタブ移動しながら金額をカンマ区切りにするサンプルです。
FLEX(AIR)で、一覧表示を作る場合、DataGrid
を利用しますね。しかし、ヘッダ部分をグループ化して表示したい ( Excelでいうセル結合した状態のようなもの ) などのニーズがあった場合、DataGrid
ではなく、AdvancedDataGrid
を利用します。
今回はこの AdvancedDataGrid
とItemrenderer
を使って「タブ移動しながら数値の入力を行い、カンマ区切り表示するサンプル」を紹介します。
Sponsored Links
目次
完成図
完成図はこんな感じになります。
Sponsored Links
ソース
それでは実際のソースを見ながら解説してきます。
NumericTextInputRenderer.as
数値入力用の ItemRenderer
です。
package { import flash.events.Event; import flash.events.FocusEvent; import mx.containers.HBox; import mx.controls.AdvancedDataGrid; import mx.controls.dataGridClasses.DataGridListData; import mx.controls.listClasses.BaseListData; import mx.controls.listClasses.IDropInListItemRenderer; import mx.controls.listClasses.IListItemRenderer; import mx.managers.IFocusManager; import mx.managers.IFocusManagerComponent; /** * 数値入力レンダラー */ public class NumericTextInputRenderer extends HBox implements IListItemRenderer, IDropInListItemRenderer, IFocusManagerComponent { /** * コンストラクタ */ public function NumericTextInputRenderer() { super(); } /** * NumericTextInput */ private var textInput:NumericTextInput = null; /** * listData */ private var _listData:BaseListData; [Bindable("dataChange")] [Inspectable(environment="none")] public function get listData():BaseListData { return this._listData; } public function set listData(value:BaseListData):void { this._listData = value; } /** * TextInputのID */ private var _tid:String = ""; public function get tid():String { return this._tid; } public function set tid(tid:String):void { this._tid = tid; } /** * @private * Create components that are children of this Container. */ override protected function createChildren():void { super.createChildren(); this.textInput = new NumericTextInput(); this.textInput.width = 100; this.textInput.maxChars = 16; this.textInput.imeMode = "ALPHANUMERIC_HALF"; this.textInput.precision = 0; // 小数点以下の表示桁数 this.id = _tid; this.textInput.addEventListener(FocusEvent.FOCUS_OUT, function(event:FocusEvent):void { if ( event.currentTarget.text == "" ) return; var dgOwner:AdvancedDataGrid = event.currentTarget.owner.owner as AdvancedDataGrid; var idx:int = dgOwner.selectedIndex; data[DataGridListData(_listData).dataField] = event.currentTarget.text; dgOwner.dataProvider[idx][DataGridListData(_listData).dataField] = event.currentTarget.text; dgOwner.validateNow(); dgOwner.dispatchEvent(event); }); addChild(this.textInput); } /** * 表示処理 */ override protected function commitProperties():void { super.commitProperties(); if ( data != null ) this.textInput.text = data[DataGridListData(_listData).dataField]; } /** * フォーカスセット */ override public function setFocus():void { var fm:IFocusManager = this.focusManager; if (IFocusManagerComponent(this.textInput) != fm.getFocus()) fm.setFocus(IFocusManagerComponent(this.textInput)); } } }
カスタムコンポーネントで、TAB キー押下時にフォーカスを移動するためには、カスタムコンテナに IFocusManagerComponent
インタフェースを実装します。
createChildren
createChildren
メソッドをオーバーライドし、子コンポーネントである、NumericTextInput
を生成します。NumericTextInput
については「Flex TextInputで数値のみ入力できてカンマ区切りにするサンプル」を参考にしてください。
フォーカスアウト時に、入力データをリストデータに書き換えるために、FOCUS_OUT イベントを追加しています。
commitProperties
commitProperties
メソッドをオーバーライドします。リストデータに値が存在する場合は、TextInput
に表示します。
setFocus
IFocusManager
を利用し、フォーカスセットをおこないます。
CharacterTextInputRenderer.as
文字列入力用の ItemRenderer
です。
package { import mx.containers.HBox; import mx.controls.dataGridClasses.DataGridListData; import mx.controls.listClasses.BaseListData; import mx.controls.listClasses.IDropInListItemRenderer; import mx.controls.listClasses.IListItemRenderer; import mx.managers.IFocusManager; import mx.managers.IFocusManagerComponent; /** * 文字列入力レンダラー */ public class CharacterTextInputRenderer extends HBox implements IListItemRenderer, IDropInListItemRenderer, IFocusManagerComponent { /** * コンストラクタ */ public function CharacterTextInputRenderer() { super(); } private var textInput:CharacterTextInput = null; /** * listData */ private var _listData:BaseListData; [Bindable("dataChange")] [Inspectable(environment="none")] public function get listData():BaseListData { return this._listData; } public function set listData(value:BaseListData):void { this._listData = value; } /** * TextInputのID */ private var _tid:String = ""; public function get tid():String { return this._tid; } public function set tid(tid:String):void { this._tid = tid; } /** * @private * Create components that are children of this Container. */ override protected function createChildren():void { super.createChildren(); this.textInput = new CharacterTextInput(); this.textInput.width = 150; this.textInput.maxChars = 80; addChild(this.textInput); } /** * 表示処理 */ override protected function commitProperties():void { super.commitProperties(); if ( data != null ) this.textInput.text = data[DataGridListData(_listData).dataField]; } /** * フォーカスセット */ override public function setFocus():void { var fm:IFocusManager = this.focusManager; if (IFocusManagerComponent(this.textInput) != fm.getFocus()) fm.setFocus(IFocusManagerComponent(this.textInput)); } } }
NumericTextInputRenderer.as とやっていることは同じですので、説明は割愛します。
子コンポーネントとして利用している CharacterTextInput
については「Flex クリックやフォーカスイン時にTextInputのテキストを選択状態にするサンプル」を参考にしてください。
AdvancedDataGridInputTest.mxml
<?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" width="544" height="312" xmlns:local="*" initialize="onInit()"> <fx:Script> <![CDATA[ import mx.collections.ArrayCollection; import mx.events.AdvancedDataGridEvent; import mx.events.AdvancedDataGridEventReason; import mx.formatters.NumberFormatter; import mx.utils.ObjectProxy; /** * 初期化 */ protected function onInit():void { StyleManager.getStyleManager(null).loadStyleDeclarations("css/blue.swf"); companyName.setFocus(); } [Bindable] private var arr:Array = [ { no: "1", debitAccountsTitle: "現金", debitPrice: "20,000", creditAccountsTitle: "当座預金", creditPrice: "20,000" }, { no: "2", debitAccountsTitle: "受取手形", debitPrice: "30,000", creditAccountsTitle: "売掛金", creditPrice: "30,000" }, { no: "3", debitAccountsTitle: "仮払金", debitPrice: "70,000", creditAccountsTitle: "現金", creditPrice: "70,000" }, { no: "4", debitAccountsTitle: "仕入", debitPrice: "100,000", creditAccountsTitle: "支払手形", creditPrice: "100,000" }, { no: "5", debitAccountsTitle: "売掛金", debitPrice: "200,000", creditAccountsTitle: "売上高", creditPrice: "200,000" }, ]; private function summary():void { errorMsg.text = ""; var debitTotal:Number = 0; var creditTotal:Number = 0; for ( var i:int = 0; i < arr.length; i++ ) { debitTotal += Number(dataList.dataProvider[i].debitPrice.replace(new RegExp(",", "g"), "")); creditTotal += Number(dataList.dataProvider[i].creditPrice.replace(new RegExp(",", "g"), "")); } debitPriceTotal.text = format(debitTotal.toString()); creditPriceTotal.text = format(creditTotal.toString()); if ( debitPriceTotal.text != creditPriceTotal.text ) errorMsg.text = "借方と貸方の合計金額が一致しません" } private function format(text:String):String { var nf:NumberFormatter = new NumberFormatter(); nf.useThousandsSeparator = true; nf.useNegativeSign = true; return nf.format(text); } ]]> </fx:Script> <fx:Declarations> <fx:Component id="debitAccountsTitleRenderer"> <local:CharacterTextInputRenderer horizontalGap="0" borderStyle="none" color="0x000000" horizontalScrollPolicy="off" tid="debitAccountsTitle" /> </fx:Component> <fx:Component id="debitPriceRenderer"> <local:NumericTextInputRenderer horizontalGap="0" borderStyle="none" color="0x000000" horizontalScrollPolicy="off" textAlign="right" tid="debitPrice" /> </fx:Component> <fx:Component id="creditAccountsTitleRenderer"> <local:CharacterTextInputRenderer horizontalGap="0" borderStyle="none" color="0x000000" horizontalScrollPolicy="off" tid="creditAccountsTitle" /> </fx:Component> <fx:Component id="creditPriceRenderer"> <local:NumericTextInputRenderer horizontalGap="0" borderStyle="none" color="0x000000" horizontalScrollPolicy="off" textAlign="right" tid="creditPrice" /> </fx:Component> </fx:Declarations> <mx:VBox width="100%" > <mx:HBox width="100%"> <mx:FormItem width="100%" label="会社名"> <local:CharacterTextInput id="companyName" text="saka-en." width="100%" maxChars="40" /> </mx:FormItem> </mx:HBox> <mx:AdvancedDataGrid id="dataList" width="100%" initialize="dataList.dataProvider=arr" rowCount="7" allowMultipleSelection="true" editable="true" itemEditEnd="event.reason = AdvancedDataGridEventReason.CANCELLED" > <mx:groupedColumns> <mx:AdvancedDataGridColumn dataField="no" width="35" headerText="No." textAlign="right" editable="false"/> <mx:AdvancedDataGridColumnGroup headerText="借方"> <mx:AdvancedDataGridColumn dataField="debitAccountsTitle" width="150" headerText="勘定科目" itemRenderer="{debitAccountsTitleRenderer}" rendererIsEditor="true" editable="true" /> <mx:AdvancedDataGridColumn dataField="debitPrice" width="100" headerText="金額" itemRenderer="{debitPriceRenderer}" rendererIsEditor="true" editable="true" /> </mx:AdvancedDataGridColumnGroup> <mx:AdvancedDataGridColumnGroup headerText="貸方"> <mx:AdvancedDataGridColumn dataField="creditAccountsTitle" width="150" headerText="勘定科目" itemRenderer="{creditAccountsTitleRenderer}" rendererIsEditor="true" editable="true" /> <mx:AdvancedDataGridColumn dataField="creditPrice" width="100" headerText="金額" itemRenderer="{creditPriceRenderer}" rendererIsEditor="true" editable="true" /> </mx:AdvancedDataGridColumnGroup> </mx:groupedColumns> </mx:AdvancedDataGrid> <mx:HBox width="100%"> <mx:FormItem width="100%" label="借方計"> <mx:HBox width="100%" styleName="total"> <mx:Spacer width="100%" /> <mx:Text id="debitPriceTotal" text="0" /> </mx:HBox> </mx:FormItem> <mx:FormItem width="100%" label="貸方計"> <mx:HBox width="100%" styleName="total"> <mx:Spacer width="100%" /> <mx:Text id="creditPriceTotal" text="0" /> </mx:HBox> </mx:FormItem> </mx:HBox> <mx:HBox width="100%"> <mx:Button id="sum" label="総額表示" click="summary()" /> <mx:HBox width="100%" styleName="errorMsgBox"> <mx:Text id="errorMsg" height="20" /> </mx:HBox> </mx:HBox> </mx:VBox> </s:Application>
Sponsored Links
サンプルソースのダウンロード
サンプルソースは、こちら からダウンロードできます。
おつかれさまでした。
Sponsored Links