Example of Designing Loosely Coupled Flex 2 Components — pass data from main to child component

There is a good article regarding Designing Loosely Coupled Flex 2 Components. This is a good place to learn about different ways to design your components in Flex 2. On the third page of this article, it demonstrated how to Create Custom Event ActionScript Classes for sending complex data with an example. This example shows how to send data to the parent page by dispatch an event from the child component. What if you want to dispatch the event from the parent page, and pass the data into the child? Here is a simple example to show how we can accomplish that.

1. create a customer event ActionScript class:

In order to pass extra data via event, a customer event class is needed. We do this by extends existing Flex event classes and inherit all the events of the base class.  Here we create myEvent.as to pass selectedAlbum with the event.

myEvent.as:

package
{
     import flash.events.Event;
     import mx.core.Application;

    public class myEvent extends Event
   {
            public var myAlbum:String;
            public function myEvent(selectedAlbum:String,type:String) {
                     super(type);
                     this.myAlbum = selectedAlbum;
                     Application.application.lb.text=myAlbum;
           }
           public override function clone():Event{
                    return new myEvent(myAlbum,type);
           }
  }
}

2.  Create the main application:

The main application has a datagrid. The goal is to be able to display data in a new state based on selected row in the datagrid. The follwoing two handlers are the most improtant:

1).datagrid’s itemClick event handler itemClickEvent():  this will get the selected row and value of selectedAlbum.

2).eventHandler(): this will display the new state, dispatch event myEvent (must make sure the event is dispatched after the child is created), and pass selectedAlbum to the child component. We reference the child component as <v:looselyCoupledChild />.

Note, eventObj = new myEvent(selectedAlbum,"passID");

Here, passID is the event name we will define in the Metadata of the child component:

<mx:Metadata>
[Event(name="passID", type="myEvent")]
</mx:Metadata>

main flex page looselyCoupled.mxml:

<?xml version="1.0" encoding="utf-8"?>

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:v="*" layout="vertical">

<!–This example passes selectedAlbum to child.mxml by listening  to myEvent –>        

<mx:Script>

        <![CDATA[    

                      import flash.events.EventDispatcher;

                      import mx.events.ListEvent;

                      import mx.collections.ArrayCollection;

                      [Bindable]

                      public var selectedAlbum:String;

                      public var eventObj:myEvent;

                      [Bindable]

                      private var initDG:ArrayCollection = new ArrayCollection([

            {Artist:'Pavement', Album:'Slanted and Enchanted', 

                      Price:11.99, SalePrice: true },

            {Artist:'Pavement', Album:'Brighten the Corners',   

                      Price:11.99, SalePrice: false }

          ]);  

        private function itemClickEvent(event:ListEvent):void {

                                    selectedAlbum=event.currentTarget.selectedItem.Album;

                                    eventObj = new myEvent(selectedAlbum,"passID");

                                    this.dispatchEvent(eventObj);

                                    lb1.text=eventObj.myAlbum;

      }

                             private function eventHandler(stateView:String):void{

                             //the stateView must be created before the event dispatch.

                                    this.currentState = stateView;

                                    dispatchEvt();

                      }

                      private function dispatchEvt():void{

                                    eventObj = new myEvent(selectedAlbum,"passID");

                                    this.dispatchEvent(eventObj);                                

                      }                

        ]]>

</mx:Script>

<mx:Label id="lb"  text="show selectedAlbum — from myEvent"/>

<mx:Label id="lb1"  text="show selectedAlbum — from eventObj.myAlbum"/>

<mx:DataGrid  id="dg" dataProvider="{initDG}"  itemClick="itemClickEvent(event)">

</mx:DataGrid>

<mx:Button x="117" y="240" label="dispaly Album"  id="bt" click="eventHandler(‘child’)" />

          <mx:states>

                        <mx:State name="child">

                                      <mx:AddChild position="lastChild">

                                                                <v:looselyCoupledChild />

                                      </mx:AddChild>

                        </mx:State>

          </mx:states>     

</mx:Application>

3. create the child component:

In the child component, we need to add event listener to listen to passID as following:   Application.application.addEventListener("passID", passIDHandler);

looselyCoupledChild.mxml:

<?xml version="1.0" encoding="utf-8"?>
<mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="300" initialize="initHandler()" >
<mx:Metadata>
[Event(name="passID", type="myEvent")]
</mx:Metadata>
<mx:Script>
<![CDATA[

import mx.core.Application;
import myEvent;
private function initHandler():void{
Application.application.addEventListener("passID", passIDHandler);
}

private function passIDHandler(event:myEvent):void {
tinput.text = event.myAlbum;
}

]]>
</mx:Script>

<mx:Label text="Album you selected from event:" x="26" y="10"/>
<mx:TextInput x="107" y="8" id="tinput" />
<mx:Label x="291" y="10" text="Album you selected from selectedAlbum:"/>
<mx:TextInput x="372" y="8" text="{Application.application.selectedAlbum}"/>

</mx:Panel>

Note, Application.application.addEventListener("passID", passIDHandler);
  This means we will always have a reference to the child. If you are concerned about memory issue, you should check and destroy the event when it is done. If you don’t want to destroy the event, you can set weakRef to true in addEventListener.

To test the sample,

1). run looselyCoupled.mx, and select a row. You will see the Album name displayed on top of the datagrid.

2). click on "dispaly Album" Button, you will see the Album name has passed into the child component.

3). select another row in the datagrid, you will see the value in the child component is changed as well.