新規従業員用モデルの追加
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の搭載機能をデモするサンプルが多数収録されています。

fName:String,lName:String,location:String):Void
{
