Welcome!

Adobe Flex Authors: Liz McMillan, RealWire News Distribution, Maureen O'Gara, Yakov Fain, Keith Swenson

Related Topics: Adobe Flex

Adobe Flex: Article

Designing Loosely Coupled Flex 2 Components

Powerful tools

Creating Custom Event Actionscript Classes for sending complex data
With Flex it's possible to create a custom event that uses an event object of a customized type. One just needs to create a subclass that extends the Event class and adding properties to it. Don't forget that custom components that extend existing Flex classes inherit all the events of the base class.

To develop a subclass we have to create an actionscript class that typicaly extends the flash.events.Event class, the base class for all event objects. After that we call the super() method of the Event class in order to call the constructor of the superclass and pass the event type to it. We are required to override the "clone()" method to return a new copy of the event object by setting the type property and any new properties.

To dispatch a new event from your custom component we create a new istance of the custom actionscript class and we pass properties to it.

Let me show you a real example to explain this approach. We develop a simple blog reader that allows users to select from a list of blogs using a combo bo. The application is made up of 2 MXML components that contain the DataGrid, to show the blog's post, and a combobox with the blog's list.

We'll start from the custom event class ( saved as "evtClass.as" placed into the "com" folder) that accepts a simple String property :

package com
{
    import flash.events.Event;

    public class evtClass extends Event
    {

public var evProp:String;

      public function evtClass(evParam:String,type:String)
      {
        super(type);
        this.evProp = evParam;
      }
        override public function clone():Event
      {
        return new evtClass(evProp,type);
      }
    }
}

As we said before, our class extends the flash.events.Event class, calls the super() method of the Event class and overrides the clone() method.

Now, create the first component from your Flex Builder 2 (File > New > MXML Component) and save it as custBlogList.mxml. This component contains the combobox and defines its dataprovider as an ArrayCollection object :

<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" >

   <mx:Metadata>
     [Event(name="changeBlog", type="com.evtClass")]
   </mx:Metadata>

   <mx:Script>
     <![CDATA[

       import com.evtClass;
       private function init():void
       {
       myArray.addItemAt({label:"Alistair McLeod", data:"http://weblogs.macromedia.com/amcleod/index.xml"}, 0);
       }
       private function changeHandler():void
       {
         var eventObj:evtClass = new evtClass(myCombo.value as String,"changeBlog");
         dispatchEvent(eventObj);
       }

     ]]>
   </mx:Script>

   <mx:ComboBox id="myCombo" change="changeHandler()" creationComplete="init();myCombo.selectedIndex=0" >
   <mx:ArrayCollection id="myArray">
     <mx:Object label="Mike Chambers" data="http://weblogs.macromedia.com/mesh/index.xml"/>
     <mx:Object label="Matt Chotin" data="http://weblogs.macromedia.com/mchotin/index.xml"/>
   </mx:ArrayCollection>
</mx:ComboBox>

</mx:VBox>

We used the [Event] metadata tag that defines the events that the MXML component can dispatch. The value assigned to the type property is equal to our custom event class :

<mx:Metadata>
    [Event(name="changeBlog", type="com.evtClass")]
</mx:Metadata>

Once the user selects a blog under the ComboBox, the change event is fired and the changeHandler() is called :

<mx:ComboBox id="myCombo" change="changeHandler()" creationComplete="init();myCombo.selectedIndex=0" >

The event handler has the only purpose to create an instance of the custom event class and to pass the value selected by the user to the new istance (myCombo.value as String) :

private function changeHandler():void
      {
        var eventObj:evtClass = new evtClass(myCombo.value as String,"changeBlog");
        dispatchEvent(eventObj);
      }

The second MXML component contains the DataGrid control and accepts the dataprovider from the main application. Now you should save the file as custBlogData.mxml:

<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml">

<mx:Script>
   <![CDATA[
      import mx.collections.ArrayCollection;
      import flash.net.*;
      [Bindable]
      public var lista:ArrayCollection;
   ]]>
</mx:Script>

   <mx:DataGrid id="myDG" horizontalCenter="14" verticalCenter="18.5" dataProvider="{lista}" width="100%"
change="navigateToURL(new URLRequest(myDG.selectedItem.link),'_blank');" >
      <mx:columns>
      <mx:DataGridColumn headerText="Posts" dataField="title" />
      <mx:DataGridColumn headerText="Date" dataField="pubDate" width="100" />
   </mx:columns>
   </mx:DataGrid>

   </mx:VBox>

The DataGrid defines two columns. The first one receives data from the RSS feed the user has selected (custBlogList component). The second one receives data from the ArrayCollection variable ("lista").

Last but not least there is the main application (BlogReader.mxml) file that invokes the two components, calls an HTTPService for retrieving rss data and defines the event handler function:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:cust="*"
creationComplete="hs.send()" >
   <mx:HTTPService
   id="hs"
   url="{selectedMenu}"
   useProxy="false"/>

<mx:Script>
     <![CDATA[

       import com.evtClass;

       [Bindable]
       private var selectedMenu:String= "http://weblogs.macromedia.com/amcleod/index.xml";

       private function eventFired(event:evtClass):void
       {

         selectedMenu = event.evProp;
         if (selectedMenu == "null")
         {
         mx.controls.Alert.show("Please Choose a valid Blog");
         return;
         };
         hs.send();
       }
     ]]>
   </mx:Script>

   <mx:Panel width="70%" height="70%" layout="absolute" title="Comtaste's Blog Reader" horizontalCenter="0"
     verticalCenter="-14.5">

   <mx:Label text="{hs.lastResult.rss.channel.title}'s Blog" id="myLbl" x="48.5" y="43" fontWeight="bold"/>
   <cust:custBlogList x="161" y="10" changeBlog="eventFired(event)" />
   <mx:Label x="48.5" y="10" text="Select a Blog" height="25"/>
   <cust:custBlogData width="80%" x="48.5" y="69" lista="{hs.lastResult.rss.channel.item}" />
   <mx:ControlBar>
   <mx:Label text="Developed by Marco Casario" />
   <mx:LinkButton label="http://casario.blogs.com" click="navigateToURL(new
URLRequest('http://casario.blogs.com'),'_blank');"/>
     </mx:ControlBar>
   </mx:Panel>

</mx:Application>

The HTTPService tag has a data binding for its url attribute. The {selectedMenu} value is populated when the changeBlog event of the custBlogList fires :

<mx:HTTPService
    id="hs"
    url="{selectedMenu}"
    useProxy="false"/>

<cust:custBlogList x="161" y="10" changeBlog="eventFired(event)" />

The eventFired() event handler function uses the event object to retrieve the evProp defined into the actionscript class (evtClass.as) that contains the myCombo.value :

private function eventFired(event:evtClass):void
    {
       selectedMenu = event.evProp;
       if (selectedMenu == "null")
       {
       mx.controls.Alert.show("Please Choose a valid Blog");
       return;
       };
       hs.send();
    }

Loosely coupled components are powerful tools for Flex 2 applications because they enable developers to improve the reusability and maintainability of their code. Using this approach is possible to define logic modules that respond to different user interactions throughout multiple applications.

Modules can also be customized with properties to pass information with one another and events to return information back.

More Stories By Marco Casario

Marco Casario is CEO of Comtaste, a company devoted to develop Rich Internet Applications on the Web and for mobile devices.

He collaborates intensively with Adobe Italy as a speaker at conferences and as a consultant for Flash, Flex, and Flash Lite.

Learn more about Marco Casario at his blog http://casario.blogs.com. In 2005, Marco has founded Comtaste, a company dedicated to exploring new frontiers in Rich Internet Applications and the convergence between the web and the world of mobile devices — MobyMobile and YouThru are representative of their recent work. He is founder of the biggest worldwide Flash Lite User Group and of www.augitaly.com, a reference point for the Italian community of Adobe users, in which he carries out the role of Channel Manager for the section dedicated to Flex.

Comments (1) View Comments

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.


Most Recent Comments
saravanan 11/23/07 12:44:26 AM EST

HI,

this is exellent tutorials..i have learned lot about using custom events in MXML and AS

But one more thing there is no change event for datagrid please check it , use some valid event for that ..