Component Class – Part Two

In the previous article I showed you how to make a component based on an existing MXML component, the HBox. In this article we’ll look at writing that same component in ActionScript. I think this is a worthwhile exercise because you’ll see how similar MXML and ActionScript components are.

One good thing to try is to add
-keep-generated-actionscript=true to your Flex compiler options. MXML files are first translated into ActionScript classes, then compiled into the SWF file. The
-keep-generated-actionscript switch will leave those translations and you can compare what we’re about to do with what the compiler has generated.

Take a look at the V1 MXML component. There are four parts to it: the root tag (the HBox), the Event metadata, the Script block, and the child components (LinkButton and Image). You’ll see how these elements are reflected when you write the ActionScript version of the component.

Download the Source

This is the source code for this example in a package structure. The file for the icon is included.

Create a new ActionScript class called CycleSelectButtonV2 and have it extend HBox. Use the Flex Builder wizard if you can. Otherwise create the class using the following code:

package com.adobe.examples.buttons
import mx.containers.HBox;

public class CycleSelectButtonV2 extends HBox
public function CycleSelectButtonV2()

One of the four elements has already been taken care of: the class extends HBox.

The MXML component also includes event metadata. Add that to the ActionScript class just above the class definition:

package com.adobe.examples.buttons
import mx.containers.HBox;


public class CycleSelectButtonV2 extends HBox

The child components, Image and LinkButton, require ActionScript code. In the first article of this series you read how the Flex framework operates with properties being set, with commitProperties() being called, and so forth. Creating child components is also part of that framework.

When a component is being created the Flex framework invokes its
createChildren() function. This is as true for Buttons as it is for Container classes like HBox. To create the LinkButton and Image components, you’ll need to add your own override of createChildren().

Below the import statement for HBox in the V2 ActionScript file, add:

import mx.controls.LinkButton;
import mx.controls.Image;  

The MXML tags for Image and LinkButton created two members of the class. You’ll do the same here, below the class constructor function:

private var linkButton:LinkButton;
private var image:Image;  

Component children in MXML files are public. I like to make them private, but you can use protected or public if you like.

You also need to bring in the cycle button graphic. In the MXML file it was embedded directly in the Image tag. There is no ActionScript equivalent for that. Instead, add this code below the variable declarations:

private var cycleIcon:Class;  

The embed metadata tells the compiler to grab the bytes from the file and generate a class to make an image out of them. The data type of the cycleIcon variable is
Class because you don’t want to have duplicates of the image (takes too much memory) but rather have shared instances that refer to those bytes.

Now add the createChildren() function:

override protected function createChildren() : void
image = new Image();
image.width = 20;
image.height = 20;
image.source = cycleIcon;
linkButton = new LinkButton(); addChild(linkButton); super.createChildren(); }

An instance of the Image class is created, then its width and height are set as is its source property. The LinkButton is also created. Notice how both components are added as children to the component using
addChild() . This puts the children onto the component’s display list. If you do not do this the children will not appear. Creating the component children with
new and using
addChild() is equivalent to the MXML tags.

The createChildren function is called before commitProperties() so that you can apply properties to the children. You should now copy the commitProperties() function, along with the setter and getter property functions from the V1 class.

With the LinkButton and Image child components created and set, you’ve knocked off another MXML component equivalent.

In the previous article, you read that part of the Flex framework includes the measurement of the components. One of the big things the MXML component does for you is figure out the size of everything and where to place it. You’ll have to do that yourself with an ActionScript component.

Because we are using HBox as the base class for the component, the sizing and positioning of the children are taken care of. Later, when we write this component from scratch, you’ll see how to do that for yourself.

At this point the only thing missing is the click event handler on the LinkButton. To add that, go back into the createChildren() method and add the following line after the linkButton has been created:

linkButton.addEventListener(MouseEvent.CLICK, handleClick);  

You’ll need to include an import statement for with the other import statements.

Using addEventListener() is the equivalent of putting the event handler in the MXML tag.

Now copy the handleClick() function from the V1 component and make the change shown:

private function handleClick( event:MouseEvent ) : void
selectedIndex = selectedIndex + 1;

// wrap back to zero if more than the # of items in the dataProvider.
if( selectedIndex >= dataProvider.length ) selectedIndex = 0;

dispatchEvent( new Event(Event.CHANGE) );

When you are using MXML tags you have the luxury of deciding what, if any, arguments to pass to an event handler. When using addEventListener the event handler function must take a single argument of some event type. If you read the documentation on the LinkButton and look at the click event, you’ll see it dispatches a MouseEvent, so that’s the type of data that will be passed.

Open the main Flex application and change the tag from CycleSelectButtonV1 to CycleSelectButtonV2 and run it. The component should look and behave the same way.

Rotating the Arrows

I said in the previous article that, in addition to writing this component in ActionScript, we’d also rotate the arrow cycle each time the LinkButton was clicked. I’ve included the code to do that in the source download, replacing the Image. Take a look and it will be the topic of the next article in this series.

6 Responses to Component Class – Part Two

  1. Dreamer says:

    Good article! As usual.

    The translation is done now. 🙂

  2. Jeff houser says:

    Just something I caught…

    The first example downloadable source does not have invalidateProperties() in the set dataProvider method, even though you talk about it in the Blog post.

    This example is missing the same thing. As such, changing the dataPRovider causes unexpected results.
    Peter: Thanks, Jeff. I’ve updated the code.

  3. Livejasmin says:

    I don’t get it, what is with commitProperties()
    The purpose of commitProperties is to allow you to set values which depend on the values of properties already set. For example, suppose you have three properties: quantity, price, and total. Where total = quantity*price. When do you set total? You can’t set in from the price setter because you don’t know if quantity has been set. You can’t set it from quantity’s setter because price might not be set. That’s where commitProperties comes it. When commitProperties is called you know that all of your setter functions have been run. Now you can make the calculation for total safely.

  4. ALVIN says:

    Good article! As usual

  5. Derek Basch says:

    Thanks for the greate article. I couldn’t find anything on using Actionscript events with MXML components until I found this example. The magic is all in the [Event] metadata tag. It allows the MXML component to dispatch an event that an Actionscript class can respond to.

  6. Ravi says:

    It is a real good article, very helpful to me to understand custom component creation.

    Thanks Peter!!