Flex AdvancedDataGridでItemRenderer(TextInput)をタブ移動しながら金額をカンマ区切りにするサンプル

Flex AdvancedDataGridで、ItemRenderer(TextInput)をタブ移動しながら金額をカンマ区切りにするサンプルです。

Flex AdvancedDataGridでItemRenderer(TextInput)をタブ移動しながら金額をカンマ区切りにするサンプル

FLEX(AIR)で、一覧表示を作る場合、DataGrid を利用しますね。しかし、ヘッダ部分をグループ化して表示したい ( Excelでいうセル結合した状態のようなもの ) などのニーズがあった場合、DataGrid ではなく、AdvancedDataGrid を利用します。

今回はこの AdvancedDataGridItemrenderer を使って「タブ移動しながら数値の入力を行い、カンマ区切り表示するサンプル」を紹介します。


完成図

完成図はこんな感じになります。

Flex AdvancedDataGridでItemRenderer(TextInput)をタブ移動しながら金額をカンマ区切りにするサンプル

ソース

それでは実際のソースを見ながら解説してきます。

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

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>

サンプルソースのダウンロード

サンプルソースは、こちら からダウンロードできます。

おつかれさまでした。

この記事がお役に立ちましたら シェア をお願いいたします。