新規従業員用モデルの追加
FlexのModel
コンポーネントは、その使い易さから想像できないほどパワフルです。ここでは、ユーザーが入力したデータを取得するためにモデルを利用し、ハンドラメソッドがフォーム要素からデータを分離できるようにします。この場面でモデルを利用する際のポイントは、モデルがActionScriptのオブジェクトを生成する点です。Model
ブロックの中にXML
タグをネストすれば、オブジェクトにプロパティを追加することができます。したがって、次に示すMXMLとActionScriptのコードは、基本的に同じオブジェクトを生成することになります。
<mx:Model id="myModel"> <name>Maya</name> <position>System Architect</position> </mx:Model>
var myModel:Object=new Object(); myModel.name="Maya"; myModel.position="System Architect";
ここでMXMLのモデルを利用するメリットは、波括弧({ }
)を記述すれば、オブジェクトのプロパティをデータの値にバインドできることです。
<name>{nameInput.text}</name>
Application
ブロックの最初にModel
を追加し、「id="newEmpModel"
」を設定します。Model
ブロックの中に、ネスト化したXML
タグを利用して「fName
」、「lName
」、「location
」の3つのプロパティを追加します。- この3つの
XML
タグを、それぞれ「fNameInput.text
」、「lNameInput.text
」、「locCombo.selectedItem
」にバインドします。
<mx:Model id="newEmpModel"> </mx:Model>
<fName></fName> <lName></lName> <location></location>
<fName>{fNameInput.text}</fName> <lName>{lNameInput.text}</lName> <location>{locCombo.selectedItem}</location>
Form
コントロールのプロパティへのバインディングです。EmployeeモデルとLocationモデルの追加
次に、XMLファイルの外部データをインポートするためのModel
コンポーネントを2つ追加します。Model
コンポーネントを利用するもう1つのメリットは、整頓されたXMLを自動的にActionScriptのデータ構造に変換できる点です。XMLファイルをインポートするには、単にXMLファイルの完全な(あるいは一部の)URLをModel
のsource
属性に設定するだけです。
- ダウンロードしておいたソースファイルの中の「employees.xml」ファイルを開くか、完成したソースコードをもとに「employees.xml」ファイルを作成します。このファイルのルートノードの
allEmployees
には、全く同じ構成の2つのemployee
ノードが含まれており、これらは、Model
のプロパティである、「employee
」という名の配列になります。 - 「
newEmpModel
」用のModel
ブロックの後に新たなModel
を追加し、「id="empModel"
」と「source="employees.xml"
」を設定します。 - ダウンロードしておいたソースファイルの中の「locations.xml」ファイルを開くか、完成したソースコードをもとに「locations.xml」ファイルを作成します。このファイルのルートノードの
locations
には、一連のlocation
ノードが含まれています。これらは、Model
のプロパティでもある、「location
」という名の配列になります。 empModel
の後に新たなModel
を追加し、「id="locModel"
」と「source="locations.xml"
」を設定します。
<mx:Model id="empModel" source="employees.xml"/>
<mx:Model id="locModel" source="locations.xml"/>
ComboBox
と「empGrid
」用のDataGrid
を記述した際に作成済みです。バインディング情報が正しいかは、既に記述したコードを見直すことで確認できます。DataControllerクラスのインスタンス化
「data.mxml」ファイルに関する最後のステップは、DataController
クラス(後ほど作成)のインスタンス化です。クラスのインスタンス化については、「Flex基礎講座(パート2):Flex電卓アプリケーションの作成」にて詳しく解説しましたが、ActionScriptのクラスはMXMLファイル内のタグを利用してインスタンス化することができます。ただし、この際、クラスの場所を規定するための名前空間の参照を含めなければ、Flexコンパイラはクラスを見つけることができません。
Application
タグの中に新たなxmlns
プロパティを追加し、このプロパティ値に名前空間の値、「"*"
」を設定します。この際、接頭辞は不要です。Model
タグの後にDataController
タグを追加し、「id="dataController"
」を設定します。
<mx:Application xmlns:mx="http://www.macromedia.com/2003/mxml"
xmlns="*">
<DataController id="dataController"/>
- ファイルを保存します。これで「data.mxml」ファイルが完成しました。
Employeeクラスの作成
次に、アプリケーションに必要な外部ActionScriptクラスの1つ目を作成します。Employee.as
クラスは「data.mxml」が直接使用するものではありませんが、後ほど作成するDataController
クラスにインポートされ、新たな従業員用のオブジェクトを生成する役割があります。
クラス自体はシンプルであり、空のコンストラクタ関数、従業員の名前と所在地のためのプロパティ群、これらのプロパティ群に値を代入するためのメソッド、の3つの要素から構成されています。
なお、ActionScriptクラスの構成については、「Flex基礎講座(パート2):Flex電卓アプリケーションの作成」にて解説しています。
- 新規ファイルを作成し、このファイルを「flex_tutorials」ディレクトリの中に「Employee.as」として保存します。
Employee
クラスのクラス定義と、空のコンストラクタ関数を追加します。- コンストラクタ関数の前に、タイプ「
String
」の3つの未定義プロパティ「fName
」「lName
」「location
」を追加します。 - コンストラクタ関数の後に
public
メソッドのaddEmpData
を追加し、「fName
」「lName
」「location
」の3つのString
引数を受け付けるようにします。また、このメソッドの中で、各引数が、それぞれの引数と同じ名前のプロパティに代入されるようにしておきます。 - ファイルを保存します。
class Employee { // コンストラクタ関数 public function Employee() {} }
public var fName:String; public var lName:String; public var location:String;
public function addEmpData( fName:String,lName:String,location:String):Void { this.fName=fName; this.lName=lName; this.location=location; }
DataControllerクラスの作成
次に、「data.mxml」ファイルを作成した際にインスタンス化を指示しておいたDataController
クラスを作成します。このクラスには「data.mxml」のイベントを処理するためのメソッドが含まれています。また、このクラスは次の2つの追加クラスをインポートします。
Employee
:1つ前のステップで作成したActionScriptクラスmx.managers.DragManager
:ドラッグ&ドロップイベントを処理するためのプロパティやメソッドを含む、Flexクラスライブラリ内の静的クラス
ここでは、DragManager
クラスの1つのプロパティだけを使用しますが、DragManager
クラスには他にもドラッグ&ドロップ関連のルールを実装するための多くの機能性が装備されています。詳細については、Flexドキュメンテーションを参照してください。
- 新規ファイルを作成し、このファイルを「flex_tutorials」ディレクトリの中に「DataController.as」として保存します。
- ファイルの始めに、
Employee
クラスとmx.managers.DragManager
クラスをインポートするためのimport
ステートメントを記述します。 import
ステートメントの後にDataController
クラスのクラス定義と、空のコンストラクタ関数を追加します。
import mx.managers.DragManager; import Employee;
class DataController { // コンストラクタ関数 public function DataController() {} }
DataControllerのメソッドの追加
DataController
には次に挙げる3つのメソッドがあります。
addNewEmp()
メソッドは「fName
」「lName
」「location
」プロパティの備わったsrc
オブジェクトを受け付け、そこからEmployee
クラスの一時的なインスタンスを生成します。この一時的なオブジェクトは、「dest
」dataProviderに追加されます。src
とdest
が引数として渡されるので、このメソッドは、ボタンクリックとドラッグ&ドロップ操作の両データのコピーをすることができます。
src
オブジェクトを直接追加する代わりに一時的なオブジェクトを作成する必要があるのは、オブジェクトが参照として渡されるからであり、こうすることで、src
オブジェクトに対して起こった変化を、自動的に「dest
」dataProviderへ反映させることができます。doDragEnter()
メソッドは、オブジェクトの上をドラッグ中のオブジェクトが通過する際のイベントを処理します。このイベントでは、event.handled
プロパティ(デフォルト設定:「false
」)を利用して、オブジェクトがドラッグされたオブジェクトを受け付けることができるかの判断と、もし可能ならば、オブジェクトがドロップされた際にDragManager
のどの操作を行えばよいかを定義します(デフォルト設定:「なにもしない」)。doDragDrop()
メソッドは、ドラッグ中のオブジェクトがドロップされた際のイベントを処理します。この部分のロジックは、Flexが自動的に生成してハンドラに渡す、event
オブジェクトのプロパティとメソッドによって可能になります。event.dragSource.dataForFormat("items")
は、自動的に、ドラッグされたデータオブジェクトを含む配列を返します。event.target
は、ドロップイベントが発生する場所のデータを受け取ることができる、オブジェクトを返します(データグリッドの場合、このプロパティはグリッドのdataProvider
になります)。
DataController
のコンストラクタ関数の後にpublic
メソッドの「addNewEmp()
」を追加し、引数としてObject
タイプの「src
」と「dest
」を受け取り、戻り値がないように設定します。- メソッドブロックの中で
Employee
タイプの変数、「tmpObj
」を宣言し、これを新規Employee
オブジェクトとして初期化します。 tmpObj
に対して「Employee
」のaddEmpData()
メソッドを呼び出し、src
の「fName
」「lName
」「location
」プロパティを引数として渡します。dest
に対して「dataProvider」のaddItem()
メソッドを呼び出し、tmpObj
を追加します。- 新たに
doDragEnter()
という名のメソッドを追加し、event
を引数として受け付けます。このメソッドブロックの中に「event.handled=true
」と「event.action=DragManager.COPY
」を設定します。 - さらに、
doDragDrop()
という名のメソッドを追加し、このメソッドもevent
を引数として受け付けるようにします。このメソッドブロックの中で、変数のitems
に「event.dragSource.dataForFormat("items")
」、もう1つの変数dest
に「event.target
」を、それぞれ代入します。 - メソッド内に、
items
配列の1番目の要素とdest
を渡すaddNewEmp()
メソッドを追加し、ドラッグしたデータをドラッグ先のデータグリッドにコピーします。 - これで完成です。ファイルを保存してから「data.mxml」ファイルにブラウザし、動作を確認してください。新たな従業員の追加や、エンジニアリンググループまたはサポートグループのデータグリッドに従業員情報をドラッグする操作を試してください。
public function addNewEmp(src:Object,dest:Object):Void { }
var tmpObj:Employee=new Employee();
tmpObj.addEmpData(src.fName,src.lName,src.location);
dest.addItem(tmpObj);
public function doDragEnter(event):Void { event.handled=true; event.action=DragManager.COPY; }
public function doDragDrop(event):Void { var items = event.dragSource.dataForFormat("items"); var dest = event.target; }
addNewEmp(items[0],dest);
<?xml version="1.0"?> <mx:Application xmlns:mx="http://www.macromedia.com/2003/mxml"
xmlns="*"> <mx:Model id="newEmpModel"> <fName>{fNameInput.text}</fName> <lName>{lNameInput.text}</lName> <location>{locCombo.selectedItem}</location> </mx:Model> <mx:Model id="empModel" source="employees.xml"/> <mx:Model id="locModel" source="locations.xml"/> <DataController id="dataController"/> <mx:HBox> <mx:Panel id="empPanel" title="Employee Data"
height="{engPanel.height+supPanel.height}"> <mx:DataGrid id="empGrid" dragEnabled="true"> <mx:dataProvider> {empModel.employee} </mx:dataProvider> <mx:columns> <mx:Array> <mx:DataGridColumn columnName="fName"
headerText="First Name" /> <mx:DataGridColumn columnName="lName"
headerText="Last Name" /> <mx:DataGridColumn columnName="location"
headerText="Location" /> </mx:Array> </mx:columns> </mx:DataGrid> <mx:Form> <mx:FormHeading label="Add New"/> <mx:FormItem label="First Name"> <mx:TextInput id="fNameInput"/> </mx:FormItem> <mx:FormItem label="Last Name"> <mx:TextInput id="lNameInput"/> </mx:FormItem> <mx:FormItem label="Location"> <mx:ComboBox id="locCombo"
dataProvider="{locModel.location}"/> </mx:FormItem> </mx:Form> <mx:ControlBar> <mx:Button label="Add Employee"
click="dataController.addNewEmp (newEmpModel,empGrid.dataProvider)"/> </mx:ControlBar> </mx:Panel> <mx:VBox> <mx:Panel id="engPanel" title="Engineering Group"
width="{empPanel.width}"> <mx:DataGrid dragEnter="dataController.doDragEnter(event)"
dragDrop="dataController.doDragDrop(event)"> <mx:columns> <mx:Array> <mx:DataGridColumn columnName="fName"
headerText="First Name" /> <mx:DataGridColumn columnName="lName"
headerText="Last Name" /> <mx:DataGridColumn columnName="location"
headerText="Location" /> </mx:Array> </mx:columns> </mx:DataGrid> </mx:Panel> <mx:Panel id="supPanel" title="Support Group"
width="{empPanel.width}"> <mx:DataGrid dragEnter="dataController.doDragEnter(event)"
dragDrop="dataController.doDragDrop(event)"> <mx:columns> <mx:Array> <mx:DataGridColumn columnName="fName"
headerText="First Name" /> <mx:DataGridColumn columnName="lName"
headerText="Last Name" /> <mx:DataGridColumn columnName="location"
headerText="Location" /> </mx:Array> </mx:columns> </mx:DataGrid> </mx:Panel> </mx:VBox> </mx:HBox> </mx:Application>
class Employee { // プロパティ public var fName:String; public var lName:String; public var location:String; // コンストラクタ関数 public function Employee() {} // メソッド public function addEmpData (fName:String,lName:String,location:String):Void { this.fName=fName; this.lName=lName; this.location=location; } }
import mx.managers.DragManager; import Employee; class DataController { // コンストラクタ関数 public function DataController() {} // メソッド public function addNewEmp(src:Object,dest:Object):Void { // Employee オブジェクトの作成 var tmpObj:Employee=new Employee(); // 新規データをオブジェクトのプロパティに追加 tmpObj.addEmpData(src.fName,src.lName,src.location); // employee オブジェクトをターゲットの dataProvider に追加 dest.addItem(tmpObj); } public function doDragEnter(event):Void { // ドロップ機能を有効化 event.handled=true; // action を copy に設定 event.action = DragManager.COPY; } public function doDragDrop(event):Void { /*
event.dragSource.dataForFormat("items") は
ドラッグされたデータアイテムの配列を返します
*/ var items = event.dragSource.dataForFormat("items"); // 分かりやすくするために、ドロップターゲットのための変数を設定 var dest = event.target; // アイテムのターゲットの dataProvider にコピー addNewEmp(items[0],dest); } }
<allEmployees> <employee> <fName> Clare </fName> <lName> DuPre </lName> <location> Paris </location> </employee> <employee> <fName> David </fName> <lName> Green </lName> <location> San Francisco </location> </employee> </allEmployees>
<locations> <location> Paris </location> <location> Tokyo </location> <location> Cairo </location> <location> San Franscisco </location> </locations>
つぎのステップ
是非、下記のチュートリアルも併せてご覧ください。
このチュートリアルの内容にご関心をお持ちいただけた場合は、Flexにデフォルトで含まれているサンプルアプリケーションなども一度目を通すようにしてください。Flexの搭載機能をデモするサンプルが多数収録されています。