Learning Flex – Lesson 9, Using Custom Events

To broadcast an event from a component, you use the dispatchEvent() method which is declared in the flash.events.EventDispatcher class. This is a class that UIComponent inherits from and is therefore available to all components.

The dispatchEvent method takes one argument which is the event object to be broadcast. When an event is dispatched, anything listening for it is notified.

Declaring Events for a Component

Every component must declare the events it can dispatch. Components that are subclasses of other components can also dispatch events that their parents have declared. Events are declared within metadata tags. In MXML, an event declaration looks like:

<mx:Metadata>
[Event(name="somethingHappened" type="flash.events.Event")]
</mx:Metadata>

The event type provided here is the default so it could be omitted. The metadata tag declares that it’s child elements are metadata and any metadata declarations use square brackets to define their bounds and parentheses to define attributes.

In addition to simple notifications, sometimes data also needs to be passed. The default event class does not support this but you can create a custom subclass to get around this limitation. (As dispatchEvent requires an Event instance, any custom event needs to be a subclass of Event.) You can add any extra properties or methods you require to your event class but you are required to override the clone() method. Overriding a method allows you to change the behavior provided by the superclass. When you override a method you need to match the signature of the superclass method and provide the override keyword. The clone method returns a new copy of the event object with the same values. Typically, you will define clone to return an instance of your new event class.

Event Flow and Bubbling

If the target of an event is not a visible element on the screen (eg HTTPService ) FlashPlayer can dispatch the event directly to the target. Otherwise, the event travels through the container hierarchy  from the outermost Application container to the target component and then back up.

As all components are descendants of event.EventDispatcher, they can all listen for events using the addEventListener() method. They will only be notified however, if they are part of the event flow. This flow is divided into three parts:

  • The Capture phase – moving from the base container to the one containing the target for the event.
  • The Target phase – solely the target node itself.
  • The Bubbling phase – the return trip to the base container.

You cannot intercept an event in the capture phase, only in the bubbling phase.

All instances of the Event class have a bubbles property (Boolean) that indicates if that event object will take part in the bubbling phase of the flow. This property is set to false by default for newly created events (but some built in events such as click have it set true).¬† The flash.events.Event class takes an optional second argument to it’s constructor to indicate if the event should bubble. If bubbling is set true, ancestor containers of the target can listen for the event. Remember that even if the target element does not listen for an event leaving it for an ancestor via bubbling, if it’s a custom event, the target must declare it via a metadata tag.

Learning Flex – Lesson 5, Handling Events

Flex Events come in two types, user events (such as clicking a mouse or pressing a key) and system events (such as a component changing visibility or finishing instantiation).

Event handlers can be specified within a component tag in MXML for instance, a click event for a button could be handled like this –

<mx:Button id="myButton" click="myButton.label='clicked!'"/>

Flex expects an ActionScript  expression in this case and the single quotes are used to define the string within the overall handler expression.

Other than for trivial tasks, event handlers are normally written as ActionScript functions that may be defined externally or within a Script block. These are then called from the event handler spec such as click="clickHandler()".

Writing ActionScript code within a Script tag requires CDATA escaping as the ActionScript code is not valid XML. This is achieved by wrapping it with <![CDATA[ and ]]> so it is ignored by the XML parser.

Passing parameters to the handler is achieved by placing values between the parentheses. In the handler function, the passed value is given a type so the compiler knows what to expect. An example would be:

<mx:Script>
<![CDATA[
private function clickHandler(display:String):void
{
myButton.label = display;
}
]]>
</mx:Script>
<mx:Button id="myButton" click="clickHandler('clicked!')"/>

Creation Complete Event

An example of a system event is CreationComplete which is fired when a component has been initialized and placed in the application. The component will be visible at this time unless it’s visible property is false.

The CreationComplete event of a container is fired when it’s children have all broadcast their CreationComplete events and this process continues up the chain all the way to the final Application object.

This means that if we have components within a container, the order of event dispatch would be the components first, then the container, then the application.

Event Objects

Flex creates an event object each time an event is dispatched. This object contains information about the event that occurred. This object is often passed to the event handler so it may access properties from it.

The base event class is used as the common denominator for more specific event classes. This means that all event types have some common properties including type – the type of event that was fired and target which is a reference to the component object that caused the event.