Beta 2
Beta 2
® ™
Adobe Flex 3
Creating and Extending Flex Components
ADOBE FLEX 3 BETA 2 ii
Creating and Extending Flex Components
The Flex Builder 3 software contains code provided by the Eclipse Foundation (“Eclipse Code”). The source code for
the Eclipse Code as contained in Flex Builder 3 software (“Eclipse Source Code”) is made available under the terms
of the Eclipse Public License v1.0 which is provided herein, and is also available at http://www.eclipse.org/legal/epl-
v10.html.
Adobe Systems Incorporated, 345 Park Avenue, San Jose, CA 95110-2704, USA.
Notice to U.S. government end users. The software and documentation are “Commercial Items,” as that term is
defined at 48 C.F.R. §2.101, consisting of “Commercial Computer Software” and “Commercial Computer Software
Documentation,” as such terms are used in 48 C.F.R. §12.212 or 48 C.F.R. §227.7202, as applicable. Consistent with
48 C.F.R. §12.212 or 48 C.F.R. §§227.7202-1 through 227.7202-4, as applicable, the Commercial Computer Software
and Commercial Computer Software Documentation are being licensed to U.S. Government end users (a) only as
Commercial items and (b) with only those rights as are granted to all other end users pursuant to the terms and
conditions herein. Unpublished-rights reserved under the copyright laws of the United States. For U.S. Government
End Users, Adobe agrees to comply with all applicable equal opportunity laws including, if appropriate, the provi-
sions of Executive Order 11246, as amended, Section 402 of the Vietnam Era Veterans Readjustment Assistance Act
of 1974 (38 USC 4212), and Section 503 of the Rehabilitation Act of 1973, as amended, and the regulations at 41 CFR
Parts 60-1 through 60-60, 60-250 ,and 60-741. The affirmative action clause and regulations contained in the
preceding sentence shall be incorporated by reference.
Part Number: 90069416 (12/06)
iv
Contents
About Flex Documentation 1
Compiling Components 40
About compiling 40
Compiling components with Flex SDK 42
Compiling components with LiveCycle Data Services ES 46
171
1
Contents
Using this manual . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Accessing the Flex documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Part Description
“Creating Nonvisual Flex Components” on page 137 Describes how to create formatter, validator, and effect components for Flex.
Documentation set
The Flex documentation set includes the following titles:
Book Description
Getting Started with Flex Contains an overview of Flex features and application development procedures.
Flex Developer’s Guide Describes how to develop your dynamic web applications.
Creating and Extending Flex Components Describes how to create and extend
Flex components.
ADOBE FLEX 3 2
Creating and Extending Flex Components
Book Description
Building and Deploying Flex Applications Describes how to build and deploy
Flex applications.
Migrating Applications to Flex 2 Provides an overview of the migration process, and detailed descriptions of
changes in Flex and ActionScript.
Using Flex Builder Contains comprehensive information about all Adobe® Flex™ Builder™ 2 features,
for every level of Flex Builder users.
Adobe Flex Language Reference Provides descriptions, syntax, usage, and code examples for the Flex API.
Typographical conventions
The following typographical conventions are used in this book:
• Italic font indicates a value that should be replaced (for example, in a folder path).
• Code font indicates code.
Contents
About creating components. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
Creating custom components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
Where to go from here . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Maintainability By developing your application in discrete modules, you can isolate and debug errors faster than you
could if you developed your application in a single file.
ADOBE FLEX 3 5
Creating and Extending Flex Components
In Flex, a module corresponds to a custom component, implemented either in MXML or in ActionScript. The
following image shows an example of a Flex application divided into components:
<mx:Application> ActionScript
classes
<..>
*.AS
*.MXML *.SWF
*.AS
Use <mx:Script>
to write, import,
or include
ActionScript *.AS
<..>
*.MXML
*.AS
SWC and RSL files
UIComponent
VBox
Note: For a complete description of the class hierarchy, see the Adobe Flex Language Reference.
All visual components are derived from the UIComponent ActionScript class. Flex nonvisual components are also
implemented as a class hierarchy in ActionScript. The most commonly used nonvisual classes are the Validator,
Formatter, and Effect base classes.
You create custom components by extending the Flex class hierarchy using the MXML and ActionScript languages.
Components inherit the properties, methods, events, styles, and effects of their superclasses.
Button.as
MyASButton.as MyMXMLButton.mxml
package <mx:Button>
{
public class MyASButton extends Button <mx:Script>
{
// Override inherited methods
// Override inherited methods // and properties.
// and properties.
// Define new methods
// Define new methods // and properties.
// and properties.
// Define custom logic
// Define custom logic // in ActionScript.
// in ActionScript.
} </mx:Script>
}
<!-- Add MXML code. -->
</mx:Button>
Both implementations create a component as a subclass of the Button class and, therefore, inherit all of the public
and protected properties, methods, and other elements of the Button class. Within each implementation, you can
override inherited items, define new items, and add your custom logic.
Note: You cannot override an inherited property defined by a variable, but you can override a property defined by setter
and getter methods. You can reset the value of an inherited property defined by a variable. You typically reset it in the
constructor of the subclass for an ActionScript component, or in an event handler for an MXML component because
MXML components cannot define a constructor.
However, when you use MXML, the Flex compiler performs most of the overhead required to create a subclass of a
component for you. This makes it much easier to create components in MXML than in ActionScript.
• Almost anything that you can do in a custom ActionScript custom component, you can also do in a custom
MXML component. However, for simple components, such as components that modify the behavior of an existing
component or add a basic feature to an existing component, it is simpler and faster to create them in MXML.
• When your new component is a composite component that contains other components, and you can express the
positions and sizes of those other components using one of the Flex layout containers, you should use MXML to
define your component.
• To modify the behavior of the component, such as the way a container lays out its children, use ActionScript.
• To create a visual component by creating a subclass from UIComponent, use ActionScript.
• To create a nonvisual component, such as a formatter, validator, or effect, use ActionScript.
• To add logging support to your control, use ActionScript. For more information, see “Logging” on page 174 in
Building and Deploying Flex Applications.
Note: The Flash Professional 8 authoring environment does not support ActionScript 3.0. Therefore, you should not use
it to create ActionScript components for Flex 2. Instead, you should use the Flex Builder IDE.
For more information on custom MXML components, see “Creating Simple MXML Components” on page 49. For
more information on ActionScript components, see “Creating Simple Visual Components in ActionScript” on
page 80.
<mx:String>AK</mx:String>
<mx:String>AL</mx:String>
<!-- Add all other states. -->
</mx:dataProvider>
</mx:ComboBox>
This example shows the following:
1 The first line of the custom MXML component definition specifies the declaration of the XML version.
2 The first MXML tag of the component, called its root tag, specifies a Flex component or a custom component.
MXML components correspond to ActionScript classes, therefore, the root tag specifies the superclass of the MXML
component. In this example, the MXML component specifies the Flex ComboBox control as its superclass.
3 The xmlns property in the root tag specifies the Flex XML namespace. In this example, the xmlns property
indicates that tags in the MXML namespace use the prefix mx:.
4 The remaining lines of the component specify its definition.
The main application, or any other MXML component file, references the StateComboBox component, as the
following example shows:
<?xml version="1.0"?>
<!-- intro/IntroMyApplication.mxml -->
<!-- Include the namespace definition for your custom components. -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:MyComp="*">
</mx:Application>
The MXML tag name for a custom component is composed of two parts: the namespace prefix, in this case MyComp,
and the tag name. The namespace prefix tells Flex where to look for the file that implements the custom component.
The tag name corresponds to the filename of the component, in this case StateComboBox.mxml. Therefore, a file
named StateComboBox.mxml defines a component with the tag name of <namespace:StateComboBox>.
As part of the <mx:Application> tag, the main application file includes the following namespace definition:
xmlns:MyComp="*". This definition specifies that the component is in the same directory as the main application
file, or in a directory included in the ActionScript classpath. For more information on deploying MXML compo-
nents, see “Creating Simple MXML Components” on page 49.
Best practice is to put your custom components in a subdirectory of your application. That practice helps to ensure
that you do not have duplicate component names because they have a different namespace. If you stored your
component in the myComponents subdirectory of your application, you would specify the namespace definition as
xmlns:MyComp="myComponents.*".
The StateComboBox.mxml file specifies the ComboBox control as its root tag, so you can reference all of the
properties of the ComboBox control in the MXML tag of your custom component, or in the ActionScript specified
in an <mx:Script> tag. For example, the following example specifies the ComboBox.rowCount property and a
listener for the ComboBox.close event for your custom control:
<?xml version="1.0"?>
<!-- intro/MyApplicationProperties.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="myComponents.*">
<mx:Script>
<![CDATA[
import flash.events.Event;
ADOBE FLEX 3 10
Creating and Extending Flex Components
</mx:Application>
For more information on MXML components, see “Creating Simple MXML Components” on page 49.
<?xml version="1.0"?>
<!-- MyApplicationASComponent.mxml -->
<!-- Include the namespace definition for your custom components. -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="myComponents.*">
</mx:Application>
In this example, you first define the MyComp namespace that specifies the location of your custom component in the
application’s directory structure. You then reference the component as an MXML tag using the namespace prefix.
For more information, see “Creating Simple Visual Components in ActionScript” on page 80.
Deploying components
When you deploy your custom components as MXML or ActionScript files, you typically deploy them in the same
directory structure as your application files, in a directory specified in the ActionScript classpath, or for LiveCycle
Data Services ES, in the WEB-INF/flex/user_classes directory.
For security reasons, you might not deploy your custom components as source code files. Alternatively, you can
deploy your components as SWC files or as part of a Runtime Shared Library (RSL).
A SWC file is an archive file for Flex components. SWC files make it easy to exchange components among Flex devel-
opers. You need only exchange a single file, rather than the MXML or ActionScript files and images and other
resource files. In addition, the SWF file inside a SWC file is compiled, which means that the code is obfuscated from
casual view.
SWC files can contain one or more components and are packaged and expanded with the PKZip archive format. You
can open and examine a SWC file using WinZip, JAR, or other archiving tool. However, you should not manually
change the contents of a SWC file, and you should not try to run the SWF file that is in a SWC file outside of a SWC
file.
To create a SWC file, use the compc utility in the flex_install_dir/bin directory. The compc utility generates a SWC
file from MXML component source files and/or ActionScript component source files. For more information on
compc, see “Using the Flex Compilers” on page 109 in Building and Deploying Flex Applications.
One way to reduce the size of your application’s SWF file is by externalizing shared assets into stand-alone files that
can be separately downloaded and cached on the client. These shared assets are loaded by any number of applications
at run time, but only need to be transferred to the client once. These shared files are known as Runtime Shared
Libraries or RSLs.
For more information, including information on how to create an RSL file, see “Using Runtime Shared Libraries” on
page 165 in Building and Deploying Flex Applications.
Contents
Using ActionScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Using ActionScript
Before you start developing custom components, you should be familiar with basic ActionScript coding practices.
Your package statement must wrap the entire class definition. If you write your ActionScript class file to the same
directory as your other application files, you can leave the package name blank. However, as best practice, you should
store your components in a subdirectory, where the package name reflects the directory location. In this example,
write your ActionScript class file to the directory myComponents, a subdirectory of your main application directory.
Formatters are a particular type of component. You might also create a subdirectory of your application’s root
directory called myFormatters for all of your custom formatter classes. Each formatter class would then define its
package statement, as the following example shows:
package myFormatters
{
// Formatter class definition goes here.
}
If you create a component that is shared among multiple applications, or a component that might be used with third-
party components, assign a unique package name to avoid naming conflicts. For example, you might prefix your
package name with your company name, as in:
package Acme.myFormatters
ADOBE FLEX 3 14
Creating and Extending Flex Components
{
// Formatter class definition goes here.
}
When you reference a custom component from an MXML file, specify a namespace definition for the component
that corresponds to its directory location and package name, as the following example shows:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:MyComp="myFormatters.*">
...
</mx:Application>
You then specify the namespace definition for the component, as the following example shows:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="myFormatters.dataFormatters.*">
...
</mx:Application>
}
ADOBE FLEX 3 15
Creating and Extending Flex Components
There is a distinct difference between including and importing in ActionScript. Including is copying lines of code
from one ActionScript file into another. Files that you include must be located relative to the file performing the
include, or use an absolute path. Importing is adding a reference to a class file or package so that you can access
objects and properties defined by external classes.
For more information on including and importing, see “Using ActionScript” on page 30 in Flex Developer’s Guide.
}
}
The class definition of your component must be prefixed by the public keyword, or it cannot be used as an MXML
tag. A file that contains a class definition can have one, and only one, public class definition, although it can have
additional internal class definitions. Place any internal class definitions at the bottom of your source file below the
closing curly brace of the package definition.
In a single ActionScript file, you can define only one class in the package. To define more than one class in a file,
define the additional classes outside of the package body.
Note: The class definition is one of the few ActionScript constructs that you cannot use in an <mx:Script> block in an
MXML file.
Note: If you do not define a constructor, the compiler inserts one for you and adds a call to super(). However, it is
considered best practice to write a constructor and to explicitly call super(), unless the class contains nothing but static
members. If you define the constructor, but omit the call to super(), Flex automatically calls super() at the beginning
of your constructor.
In the following example, you define a constructor that uses super() to call the superclass’s constructor:
package myComponents
{
// Import necessary classes
import mx.core.Container;
import mx.controls.Button;
// Import all classes in the mx.events package
import mx.events.*;
// Public constructor.
public function MyButton()
{
// Call the constructor in the superclass.
super();
}
}
}
Note: You cannot define a constructor for an MXML component. For more information, see “About implementing
IMXMLObject” on page 77
Users of the class can access the public variables but not the private variables, as the following example shows:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="myControls.*">
Although you can define your classes to use public properties, you may find it advantageous to define properties by
using setter and getter methods. For more information, see “Defining methods” on page 17.
ADOBE FLEX 3 17
Creating and Extending Flex Components
Note: You cannot override an inherited property defined by a variable, but you can override a property defined by setter
and getter methods. You can reset the value of an inherited property defined by a variable. You typically reset it in the
constructor of the subclass for an ActionScript component, or in an event handler for an MXML component because
MXML components cannot define a constructor.
By convention, setters use the identifier value for the name of the argument.
The variable that stores the property’s value cannot have the same name as the getter or setter. By convention, precede
the name of the variables with one (_) or two underscores (__). In addition, Adobe recommends that you declare the
variable as private or protected.
Users of the class can access the public property as the following example shows:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="myControls.*" >
If the getter or setter overrides a getter or setter in a superclass, ensure that you include the override keyword, as
the following example shows:
override public function get label():String {}
override public function set label(value:String):void {}
Defining methods
Methods define the operations that your class can perform. You define methods in the body of the class. Your
methods can override a method of a superclass, or define new functionality for your components.
ADOBE FLEX 3 18
Creating and Extending Flex Components
If the method adds new functionality, you define it using the function keyword, as the following example shows:
public function myMethod():void {
// Method definition
}
If you define this method as a public method, users of the class can call it.
You can also define private methods, as the following example shows:
private function internalMethod():void {
// Method definition
}
Private methods are for internal use by the class, and cannot be called by users of the class.
If the method overrides a method in a superclass, you must include the override keyword and the signature of the
method must exactly match that of the superclass method, as the following example shows:
override protected function createChildren():void {
// Method definition
}
Your methods may take required or optional arguments. To make any of the arguments optional, assign default
values to them, as the following example shows:
override public validate(value:Object = null,
supressEvents:Boolean = false):ValidationResultEvent {
// Method definition
}
If the method takes a variable number of arguments, use the “...” syntax, as the following example shows:
function foo(n:Number, ... rest):void {
// Method definition
}
Flex creates an Array called rest for the optional arguments. Therefore, you can determine the number of
arguments passed to the method by using rest.length, and access the arguments by using rest[i].
This technique is useful when you create a subclass method that adds behavior to a superclass method but also
invokes the superclass method to perform its original behavior.
Note: Although Flex automatically calls the super() method in a constructor to execute the superclass’s constructor, you
must call super.methodName() in a method override. Otherwise, the superclass’s version of the method does not execute.
Whether you call super.myMethod() within a method override depends on your application requirement, as
follows:
• Typically, you extend the existing functionality of the superclass method, so the most common pattern is to call
super.myMethod() first in your method override, and then add your logic.
• You might need to change something before the superclass method does its work. In this case, you might call
super.myMethod() in the override after your logic.
ADOBE FLEX 3 19
Creating and Extending Flex Components
• In some method overrides, you might not want to invoke the superclass method at all. Only call
super.myMethod() if and when you want the superclass to do its work.
• Sometimes the superclass has an empty method that does nothing, which requires you to implement the
functionality in the method. In this case, you should still call super.myMethod() because in a future version of Flex,
that method might implement some functionality. For more information, see the documentation on each Flex class.
About scope
Scoping is mostly a description of what the this keyword refers to at any given point in your application. In the main
MXML application file, the file that contains the <mx:Application> tag, the current scope is the Application object
and, therefore, the this keyword refers to the Application object.
In an ActionScript component, the scope is the component itself and not the application or other file that references
the component. As a result, the this keyword inside the component refers to the component instance and not the
Flex Application object.
Nonvisual ActionScript components do not have access to their parent application with the parentDocument
property. However, you can access the top-level Application object by using the
mx.core.Application.application property.
For more information on scope, see “Using ActionScript” on page 30 in Flex Developer’s Guide.
20
Contents
About events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
Dispatching custom events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
About events
Adobe Flex applications are event-driven. Events let an application know when the user interacts with the interface,
and also when important changes happen in the appearance or life cycle of a component, such as the creation of a
component or its resizing. Events can be generated by user input devices, such as the mouse and keyboard, or by the
asynchronous operations, such as the return of a web service call or the firing of a timer.
The core class of the Flex component architecture, mx.core.UIComponent, defines core events, such as
updateComplete, resize, move, creationComplete, and others that are fundamental to all components.
Subclasses of UIComponent inherit these events.
Custom components that extend existing Flex classes inherit all the events of the base class. Therefore, if you extend
the Button class to create the MyButton class, you can use the click event, and the events that all controls inherit,
such as mouseOver or initialize, as the following example shows.
<?xml version="1.0"?>
<!-- events/EventsMyApplication.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="myComponents.*">
<mx:Script>
<![CDATA[
import flash.events.Event;
</mx:Script>
<MyComp:MyButton
click="handleClick(event);"
initialize="handleInit(event);"/>
</mx:Application>
In addition to using the events inherited from its superclasses, your custom components can define custom events.
You use custom events to support data binding, to respond to user interactions, or to trigger actions by your
component.
For more information on the Flex event mechanism, see “Using Events” on page 49 in Flex Developer’s Guide.
type String The name of the event; for example, “click”. The event constructor sets this property.
target EventDispatcher A reference to the component instance that dispatches the event. This property is set by the
dispatchEvent() method; you cannot change this to a different object.
currentTarget EventDispatcher A reference to the component instance that is actively processing the Event object. The value
of this property is different from the value of the target property during the event capture
and bubbling phase. For more information, see “Using Events” on page 49 in Flex Developer’s
Guide.
eventPhase uint The current phase in the event flow. The property might contain the following values:
bubbles Boolean Whether an event is a bubbling event. If the event can bubble, the value for this property is
true, otherwise, it is false. You can optionally pass this property as a constructor argument
to the Event class. By default, most event classes set this property to false. For more infor-
mation, see “Using Events” on page 49 in Flex Developer’s Guide.
cancelable Boolean Whether the event can be canceled. If the event can be canceled, the value for this value is
true, otherwise, it is false. You can optionally pass this property as a constructor argument
to the Event class. By default, most event classes set this property to false. For more infor-
mation, see “Using Events” on page 49 in Flex Developer’s Guide.
ADOBE FLEX 3 22
Creating and Extending Flex Components
You are required to override the Event.clone() method in your subclass. The clone() method returns a cloned
copy of the event object by setting the type property and any new properties in the clone. Typically, you define the
clone() method to return an event instance created with the new operator.
Suppose that you want to pass information about the state of your component to the event listener as part of the event
object. To do so, you create a subclass of the Event class to create an event, EnableChangeEvent, as the following
example shows:
package myEvents
{
//events/myEvents/EnableChangeEvent.as
import flash.events.Event;
// Public constructor.
public function EnableChangeEvent(type:String,
isEnabled:Boolean=false) {
// Call the constructor of the superclass.
super(type);
ADOBE FLEX 3 23
Creating and Extending Flex Components
The eventName argument specifies the name, including the package, of the event. The eventType argument
specifies the class that defines the event.
The following example identifies the enableChange event as an event that an ActionScript component can dispatch:
[Event(name="enableChange", type="myEvents.EnableChangeEvent")]
public class MyComponent extends TextArea
{
...
}
The following example shows the [Event] metadata tag within the <mx:Metadata> tag of an MXML file:
<?xml version="1.0"?>
<!-- events\myComponents\MyButton.mxml -->
<mx:Button xmlns:mx="http://www.adobe.com/2006/mxml"
click="dispatchEvent(new EnableChangeEvent('enableChanged'));">
<mx:Script>
<![CDATA[
import myEvents.EnableChangeEvent;
ADOBE FLEX 3 24
Creating and Extending Flex Components
]]>
</mx:Script>
<mx:Metadata>
[Event(name="enableChanged", type="myEvents.EnableChangeEvent")]
</mx:Metadata>
</mx:Button>
Once defined using the [Event] metadata tag, you can refer to the event in an MXML file, as the following example
shows:
<?xml version="1.0"?>
<!-- events/MainEventApp.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="myComponents.*" >
<mx:Script>
<![CDATA[
import myEvents.EnableChangeEvent;
public function
enableChangedListener(eventObj:EnableChangeEvent):void {
// Handle event.
}
]]>
</mx:Script>
</mx:Application>
If you do not identify an event with the [Event] metadata tag, the compiler generates an error if you try to use the
event name in MXML. The metadata for events is inherited from the superclass, however, so you do not need to tag
events that are already defined with the [Event] metadata tag in the superclass.
Dispatching an event
You use the dispatchEvent() method to dispatch an event. The dispatchEvent() method has the following
signature:
public dispatchEvent(event:Event):Boolean
This method requires an argument of type Event, which is the event object. The dispatchEvent() method
initializes the target property of the event object with a reference to the component dispatching the event.
You can create an event object and dispatch the event in a single statement, as the following example shows:
dispatchEvent(new Event("click"));
You can also create an event object, initialize it, and then dispatch it, as the following example shows:
var eventObj:EnableChangeEvent = new EnableChangeEvent("enableChange");
eventObj.isEnabled=true;
dispatchEvent(eventObj);
For complete examples that create and dispatch custom events, see “Creating Advanced MXML Components” on
page 61 and “Creating Simple Visual Components in ActionScript” on page 80.
ADOBE FLEX 3 25
Creating and Extending Flex Components
The Flex compiler does not examine the string passed to the constructor to determine if it is valid. Therefore, the
following code compiles, even though enableChangeAgain might not be a valid value for the type property:
var eventObj:EnableChangeEvent =
new EnableChangeEvent("enableChangeAgain");
Because the compiler does not check the value of the type property, the only time that your application can
determine if enableChangeAgain is valid is at run time.
However, to ensure that the value of the type property is valid at compile time, Flex event classes define static
constants for the possible values for the type property. For example, the Flex EffectEvent class defines the following
static constant:
// Define static constant for event type.
public static const EFFECT_END:String = "effectEnd";
If you incorrectly reference the constant in the constructor, the compiler generates a syntax error because it cannot
locate the associated constant. For example, the following constructor generates a syntax error at compile time
because MY_EFFECT_END is not a predefined constant of the EffectEvent class:
var eventObj:EffectEvent = new EffectEvent(EffectEvent.MY_EFFECT_END);
You can use this technique when you define your event classes. The following example modifies the definition of the
EnableChangeEventConst class to include a static constant for the type property:
package myEvents
{
//events/myEvents/EnableChangeEventConst.as
import flash.events.Event;
<mx:Button xmlns:mx="http://www.adobe.com/2006/mxml"
click="dispatchEvent(new
EnableChangeEventConst(EnableChangeEventConst.ENABLE_CHANGED));">
<mx:Script>
<![CDATA[
import myEvents.EnableChangeEventConst;
]]>
</mx:Script>
<mx:Metadata>
[Event(name="myEnable", type="myEvents.EnableChangeEventConst")]
</mx:Metadata>
</mx:Button>
This technique does not preclude you from passing a string to the constructor.
27
Contents
About metadata tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
Metadata tags. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
In this example, the [Event] metadata tag specifies the event name, and the class that defines the type of the event
object dispatched by the event. After you identify the event to the Flex compiler, you can reference it in MXML, as
the following example shows:
<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:MyComp="*">
<mx:Script>
<![CDATA[
function handleEnableChangeEvent(eventObj:Event):void {
...
}
]]>
</mx:Script>
<MyComp:ModalText enableChanged="handleEnableChangeEvent(event);"/>
</mx:Application>
If you omit the [Event] metadata tag from your class definition, Flex issues a syntax error when it compiles your
MXML file. The error message indicates that Flex does not recognize the enableChanged property.
ADOBE FLEX 3 28
Creating and Extending Flex Components
...
In this example, you add the [Event] metadata tag before the class definition to indicate that the class dispatches an
event named enableChanged. You also include the [Inspectable] metadata tag to indicate the default value of the
property for Flex Builder. For more information on using this tag, see “Inspectable metadata tag” on page 35.
In an MXML file, you insert the metadata tags either in an <mx:Script> block along with your ActionScript code,
or in an <mx:Metadata> block, as the following example shows:
<?xml version="1.0"?>
<!-- TextAreaEnabled.mxml -->
<mx:TextArea xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Metadata>
[Event(name="enableChange", type="flash.events.Event")]
</mx:Metadata>
<mx:Script>
<![CDATA[
[Inspectable(defaultValue="false")]
public function set enableTA(val:Boolean):void {
_enableTA = val;
this.enabled = val;
A key difference between the <mx:Metadata> and <mx:Script> tags is that text within the <mx:Metadata> tag is
inserted before the generated class declaration, but text within <mx:Script> tag is inserted in the body of the
generated class declaration. Therefore, metadata tags like [Event] and [Effect] must go in an <mx:Metadata> tag,
but the [Bindable] and [Embed] metadata tags must go in an <mx:Script> tag.
Metadata tags
The following table describes the metadata tags that you can use in ActionScript class files:
Tag Description
[ArrayElementType] Defines the allowed data type of each element of an Array. For more information, see “ArrayEle-
mentType metadata tag” on page 30.
[Bindable] Identifies a property that you can use as the source of a data binding expression. For more infor-
mation, see “Bindable metadata tag” on page 31.
[DefaultProperty] Defines the name of the default property of the component when you use the component in an
MXML file. For more information, see “DefaultProperty metadata tag” on page 32.
[Deprecated] Marks a class or class element as deprecated so that the compiler can recognize it and issue a
warning when the element is used in an application. For more information, see “Deprecated meta-
data tag” on page 33.
[Effect] Defines the MXML property name for the effect. For more information, see “Effect metadata tag”
on page 33.
[Embed] Imports JPEG, GIF, PNG, SVG, and SWF files at compile time. Also imports image assets from SWC
files.
This is functionally equivalent to the MXML @Embed syntax, as described in , “Embedding Assets,”
in Flex Developer’s Guide.
[Event] Defines the MXML property for an event and the data type of the event object that a component
emits. For more information, see “Event metadata tag” on page 34.
[Exclude] Omits the class element from the FlexBuilder tag inspector. The syntax is as follows:
[Exclude(name="label", kind="property")]
[ExcludeClass] Omits the class from the FlexBuilder tag inspector. This is equivalent to the @private tag in
ASDoc when applied to a class.
[IconFile] Identifies the filename for the icon that represents the component in the Insert bar of Adobe®
Flex™ Builder™. For more information, see “IconFile metadata tag” on page 35.
ADOBE FLEX 3 30
Creating and Extending Flex Components
Tag Description
[Inspectable] Defines an attribute exposed to component users in the attribute hints and Tag inspector of Flex
Builder. Also limits allowable values of the property. For more information, see “Inspectable meta-
data tag” on page 35.
[InstanceType] Specifies the allowed data type of a property of type IDeferredInstance. For more information, see
“InstanceType metadata tag” on page 37.
[NonCommittingChangeEvent] Identifies an event as an interim trigger. For more information, see “NonCommittingChangeEvent
metadata tag” on page 37.
[RemoteClass] Maps the ActionScript object to a Java object. For more information, see the LiveCycle Data
Services ES Developer’s Guide.
[Style] Defines the MXML property for a style property for the component. For more information on using
the [Style] metadata tag, see “Style metadata tag” on page 38.
[Transient] Identifies a property that should be omitted from data that is sent to the server when an Action-
Script object is mapped to a Java object using [RemoteClass].
The following sections describe the component metadata tags in more detail.
[ArrayElementType("String")]
public var newStringProperty:Array;
[ArrayElementType("Number")]
public var newNumberProperty:Array;
...
}
Note: The MXML compiler only checks for proper usage of the Array in MXML code; it does not check Array usage in
ActionScript code.
In this example, you specify String as the allowed data type of the Array elements. If a user attempts to assign
elements of a data type other than String to the Array in an MXML file, the compiler issues a syntax error, as the
following example shows:
<MyComp:MyTypedArrayComponent>
<MyComp:newStringProperty>
<mx:Number>94062</mx:Number>
<mx:Number>14850</mx:Number>
<mx:Number>53402</mx:Number>
</MyComp:newStringProperty>
</MyComp:MyTypedArrayComponent>
In this example, you try to use Number objects to initialize the Array, so the compiler issues an error.
You can also specify Array properties as tag attributes, rather than using child tags, as the following example shows.
<MyComp:MyTypedArrayComponent newNumberProperty="[abc,def]"/>
ADOBE FLEX 3 31
Creating and Extending Flex Components
This MXML code generates an error because Flex cannot convert the Strings {abc} and {def} to a Number.
You insert the [ArrayElementType] metadata tag before the variable definition. The tag has the following syntax:
[ArrayElementType("elementType")]
The following table describes the property of the [ArrayElementType] metadata tag:
elementType String Specifies the data type of the Array elements, and can be one of the ActionScript data type, such as
String, Number, class, or interface.
You must specify the type as a fully qualified class name, including the package.
If you omit the event name, Flex automatically creates an event named propertyChange.
For more information on data binding and on this metadata tag, see “Binding Data” on page 1079 in Flex Developer’s
Guide.
You should raise an event when any named property in a bindable property chain changes. If the property is marked
with the [Bindable] metadata tag, the Flex compiler generates the event for you. For more examples using the
[Bindable] metadata tag, see Bindable metadata tag in <i italic>Creating and Extending Flex Components.
The following example shows an example that uses the [Bindable] metadata tag for a variable and a getter property
and how to call the dispatchEvent() function:
[Bindable]
public var minFontSize:Number = 5;
[Bindable("textChanged")]
public function get text():String {
return myText;
}
If you omit the event name in the [Bindable] metadata tag, the Flex compiler automatically generates and
dispatches an event named propertyChange so that the property can be used as the source of a data binding
expression.
You should also provide the compiler with better information about an object by casting the object to a known type.
In the following example, the myList List control contains Customer objects, so the selectedItem property is cast
to a Customer object:
<mx:Model id="selectedCustomer">
<customer>
<name>{Customer(myList.selectedItem).name}</name>
<address>{Customer(myList.selectedItem).address}</address>
...
</customer>
</mx:Model>
There are some situations in which binding does not execute automatically as expected. Binding does not execute
automatically when you change an entire item of a dataProvider property.
Binding also does not execute automatically for subproperties of properties that have [Bindable] metadata, as the
following example shows:
...
[Bindable]
var temp;
// Binding is triggered:
temp = new Object();
// Binding is not triggered, because label not a bindable property
// of Object:
temp.label = foo;
...
In this code example, the problem with {temp.label} is that temp is an Object. You can solve in one of the following
ways:
• Preinitialize the Object.
• Assign an ObjectProxy to temp; all of an ObjectProxy’s properties are bindable.
• Make temp a strongly typed object with a label property that is bindable.
Binding also does not execute automatically when you are binding data to a property that Flash Player updates
automatically, such as the mouseX property.
The executeBindings() method of the UIComponent class executes all the bindings for which a UIComponent
object is the destination. All containers and controls, as well as the Repeater component, extend the UIComponent
class. The executeChildBindings() method of the Container and Repeater classes executes all of the bindings for
which the child UIComponent components of a Container or Repeater class are destinations. All containers extend
the Container class.
These methods give you a way to execute bindings that do not occur as expected. By adding one line of code, such
as a call to executeChildBindings() method, you can update the user interface after making a change that does
not cause bindings to execute. However, you should only use the executeBindings() method when you are sure
that bindings do not execute automatically.
Insert the [Deprecated] metadata tag before a property, method, or class definition to mark that element as depre-
cated. The [Deprecated] metadata tag has the following options for its syntax when used with a class, property or
method:
[Deprecated("string_describing_deprecation")]
[Deprecated(message="string_describing_deprecation")]
[Deprecated(replacement="string_specifying_replacement")]
[Deprecated(replacement="string_specifying_replacement", since="version_of_replacement")]
The following uses the [Deprecated] metadata tag to mark the dataProvider property as obsolete:
[Deprecated(replacement="MenuBarItem.data")]
public function set dataProvider(value:Object):void
{
...
}
The [Event], [Effect] and [Style] metadata tags also support deprecation. These tags support the following
options for syntax:
[Event(... , deprecatedMessage="string_describing_deprecation")]
[Event(... , deprecatedReplacement="change2")]
[Event(... , deprecatedReplacement="string_specifying_replacement",
deprecatedSince="version_of_replacement")]
These metadata tags support the deprecatedReplacement and deprecatedSince attributes to mark the event,
effect, or style as deprecated.
You insert the [Effect] metadata tag before the class definition in an ActionScript file, or in the <mx:Metadata>
block in an MXML file. The [Effect] metadata tag has the following syntax:
[Effect(name="eventNameEffect", event="eventName")]
The following table describes the properties of the [Effect] metadata tag:
eventName String Specifies the name of the event that triggers the effect.
The [Effect] metadata tag is often paired with an [Event] metadata tag, where the [Event] metadata tag defines
the event corresponding to the effect’s trigger. By convention, the name of the effect is the event name with the suffix
Effect, as the following example of an ActionScript file shows:
In an MXML file, you can define the event and effect in an <mx:Metadata> block, as the following example shows:
<mx:Metadata>
[Event(name="darken", type="flash.events.Event")]
[Effect(name="darkenEffect", event="darken")]
</mx:Metadata>
For more information on defining custom events, see “Creating Custom Events” on page 20.
The [Event] metadata tag has the following syntax:
[Event(name="eventName", type="package.eventType")]
The following table describes the properties of the [Event] metadata tag:
eventName String Specifies the name of the event, including its package name.
eventType String Specifies the class that defines the data type of the event object. The class name is either the base event
class, Event, or a subclass of the Event class. You must include the package in the class name.
The following example identifies the myClickEvent event as an event that the component can dispatch:
[Event(name="myClickEvent", type="flash.events.Event")]
If you do not identify an event in the class file with the [Event] metadata tag, the MXML compiler generates an
error if you try to use the event name in MXML. Any component can register an event listener for the event in
ActionScript by using the addEventListener() method, even if you omit the [Event] metadata tag.
ADOBE FLEX 3 35
Creating and Extending Flex Components
The following example identifies the myClickEvent event as an event that an ActionScript component can dispatch:
[Event(name="myEnableEvent", type="flash.events.Event")]
public class MyComponent extends UIComponent
{
...
}
The following example shows the [Event] metadata tag in the <mx:Metadata> tag in an MXML file:
<?xml version="1.0"?>
<!-- TextAreaEnabled.mxml -->
<mx:TextArea xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Metadata>
[Event(name="myEnableEvent", type="flash.events.Event")]
</mx:Metadata>
....
</mx:TextArea>
The fileName property specifies a PNG, GIF, or JPEG file that contains the icon, as the following example shows:
[IconFile("MyButton.png")]
public class MyButton extends Button
{
...
}
[Inspectable(attribute=value[,attribute=value,...])]
setter_getter_declarations;
The following table describes the properties of the [Inspectable] metadata tag:
category String Groups the property into a specific subcategory in the Property inspector of the Flex Builder user inter-
face. The default category is "Other".
defaultValue String or Sets the initial value in the editor that appears in the Property Inspector when you modify the attribute.
Number The default value is determined from the property definition.
enumeration String Specifies a comma-delimited list of legal values for the property. Only these values are allowed; for
example, item1,item2,item3. Notice the lack of a space character between items so that Flex Builder
does not interpret a space as a part of a valid value.
This information appear as code hints and in the Property Inspector. If you define a Boolean variable, Flex
Builder automatically shows true and false without you having to specifying them using
enumeration.
environment String Specifies which inspectable properties should not be allowed (none), which are used only for Flex Builder
(Flash), and which are used only by Flex and not Flex Builder (MXML).
format String Determines the type of editor that appears in the Property Inspector when you modify the attribute. You
can use this property when the data type of the attribute is not specific to its function. For example, for
a property of type Number, you can specify format="Color" to cause Flex Builder to open a color
editor when you modify the attribute. Common values for the format property include "Length",
"Color", "Time", "EmbeddedFile", and "File".
name String Specifies the display name for the property; for example, Font Width. If not specified, use the property’s
name, such as _fontWidth.
type String Specifies the type specifier. If omitted, use the property’s type. The following values are valid:
• Array
• Boolean
• Color
• Font Name
• List
• Number
• Object
String
If the property is an Array, you must list the valid values for the Array.
verbose Number Indicates that this inspectable property should be displayed in the Flex Builder user interface only when
the user indicates that verbose properties should be included. If this property is not specified, Flex
Builder assumes that the property should be displayed.
The Flex compiler validates that users only assign values of the specified type to the property. In this example, if the
component user sets the topRow property to a value of a type other than mx.controls.Label, the compiler issues an
error message.
You use the [InstanceType] metadata tag when creating template components. For more information, see
“Creating Template Components” on page 131.
The [InstanceType] metadata tag has the following syntax:
[InstanceType("package.className")]
In the following example, the component dispatches the change event every time the user enters a keystroke, but the
change event does not trigger data binding or data validators. When the user completes data entry, by pressing the
Enter key, the component broadcasts the valueCommit event to trigger any data bindings and data validators:
[Event(name="change", type="flash.events.Event")]
class MyText extends UIComponent {
...
[Bindable(event="valueCommit")]
[NonCommittingChangeEvent("change")]
function get text():String {
return getText();
}
function set text(t):void {
setText(t);
// Dispatch events.
}
}
ADOBE FLEX 3 38
Creating and Extending Flex Components
The following table describes the properties for the [Style] metadata tag:
type String Specifies the data type of the value that you write to the style property. If the type is not an ActionScript
type such as Number or Date, use a qualified class name in the form packageName.className.
arrayType String If type is Array, arrayType specifies the data type of the Array elements. If the data type is not an
ActionScript type such as Number or Date, use a qualified class name in the form packageName.class-
Name.
format String Specifies the units of the property. For example, if you specify type as “Number”, you might specify
format="Length" if the style defines a length measured in pixels. Or, if you specify type="uint", you
might set format="Color" if the style defines an RGB color.
enumeration String Specifies an enumerated list of possible values for the style property.
inherit String Specifies whether the property is inheriting. Valid values are yes and no. This property refers to CSS inher-
itance, not object-oriented inheritance. All subclasses automatically use object-oriented inheritance to
inherit the style property definitions of their superclasses.
Some style properties are inherited using CSS inheritance. If you set an inheritable style property on a
parent container, its children inherit that style property. For example, if you define fontFamily as Times
for a Panel container, all children of that container will also use Times for fontFamily, unless they over-
ride that property.
If you set a noninheritable style, such as textDecoration, on a parent container, only the parent
container and not its children use that style. For more information on inheritable style properties, see
“About style inheritance” in Flex Developer’s Guide.
states String For skin properties, specifies that you can use the style to specify a stateful skin for multiple states of the
component. For example, the definition of the Slider.thumbSkin style uses the following [Style]
metadata tag:
This line specifies that you can use the Slider.thumbSkin style to specify a stateful skin for the
disabled, down, over, and up states of the Slider control. For more information, see , “Creating Skins,” in
Flex Developer’s Guide.
The following example shows the definition of the textSelectedColor style property:
[Style(name="textSelectedColor",type="Number",format="Color",inherit="yes")]
The next example shows the definition of the verticalAlign style property:
[Style(name="verticalAlign", type="String", enumeration="bottom,middle,top", inherit="no")]
For more information on the [Style] metadata tag, see “Creating Custom Style Properties” on page 124.
ADOBE FLEX 3 39
Creating and Extending Flex Components
Contents
About compiling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
Compiling components with Flex SDK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
Compiling components with LiveCycle Data Services ES. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
About compiling
You compile a custom component so that you can use it as part of your application. You can compile the component
when you compile the entire application, or you can compile it separately so that you can link it into the application
at a later time.
SWC .swc A component implemented as an MXML or ActionScript file, and then packaged as a SWC file.
A SWC file contains components that you package and reuse among multiple applications. The
SWC file is then compiled into your application when you create the application’s SWF file.
RSL .swc A component implemented as an MXML or ActionScript file, and then deployed as an RSL. An
RSL is a stand-alone file that is downloaded separately from your application’s SWF file, and
cached on the client computer for use with multiple application SWF files.
You must take into consideration the file format and file location when you compile an application that uses the
component.
You can use the compc and mxmlc compilers from Adobe Flex Builder, or from a command line. For more infor-
mation on using the compilers, see “Using the Flex Compilers” on page 109 in Building and Deploying Flex Applica-
tions, and “Building Projects” on page 127 in Using Flex Builder.
This section presents some examples of using the mxmlc compiler. The most basic example is one in which the
MXML file has no external dependencies (such as components in a SWC file or ActionScript classes). In this case,
you open mxmlc and point it to your MXML file:
$ mxmlc c:/myfiles/app.mxml
The default option is the target file to compile into a SWF file, and it is required to have a value. If you use a space-
separated list as part of the options, you can terminate the list with a double hyphen before adding the target file; for
example:
$ mxmlc -option arg1 arg2 arg3 -- target_file.mxml
When LiveCycle Data Services ES receives an HTTP request for an MXML file, LiveCycle Data Services ES performs
the following steps:
1 Compiles the MXML file to produce a SWF file.
2 Caches the compiled SWF file on the server.
3 Returns the SWF file to the client.
• An MXML component does not include a package name definition. However, you must declare a namespace
definition in the file that references the MXML component that corresponds to the directory location of the MXML
component, either in a subdirectory of the application’s root directory, or in a subdirectory of the classpath. For more
information, see “Creating Simple MXML Components” on page 49.
• An application can access MXML and ActionScript components in the directories included in the ActionScript
classpath. The component search order in the classpath is based on the order of the directories listed in the classpath.
• An ActionScript component in a subdirectory of a directory included in the classpath must define a fully
qualified package name that is relative to the location of the classpath directory. For example, if you define a custom
component in the file dir1/dir2/myControls/PieChart.as, and dir1 is included in the ActionScript classpath, its fully
qualified package name must be dir1.dir2.myControls.
• The <mx:Script> tag in the main MXML file, and in dependent MXML component files, can reference compo-
nents located in the ActionScript classpath.
SWC files can contain one or more components and are packaged and expanded with the PKZIP archive format. You
can open and examine a SWC file by using WinZip, JAR, or another archiving tool. However, do not manually
change the contents of a SWC file, and do not try to run the SWF file that is in a SWC file outside of the SWC file.
When you compile your application, you specify the directory location of the SWC files by using one of the following
methods:
Flex Builder Open the Project Properties dialog box, and then select Flex Build Path to set the library directories that
contain the SWC files.
Command-line compiler Set the library-classpath option to the mxmlc compiler to specify the directory
location of your SWC files.
One of the advantages to distributing components as SWC files is that you can define a global style sheet, named
defaults.css, in the SWC file. The defaults.css file defines the default style settings for all of the components defined
in the SWC file. For more information, see “Applying styles from a defaults.css file” on page 58.
For more information about SWC files, see “Using the Flex Compilers” on page 109 in Building and Deploying Flex
Applications, and “Building Projects” on page 127 in Using Flex Builder.
You can refer to it as the following example shows. In this example, the local namespace (*) is mapped to the
prefix MyComp.
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="*">
<MyComp:MySimpleFormatter/>
</mx:Application>
If the same file exists in the ActionScript classpath directory and the application directory, Flex uses the file in
the application directory.
2 If you store the formatter component in a subdirectory of the directory that contains the application file, you
specify that directory as part of the package statement, as the following example shows:
package myComponents.formatters
{
//Import base Formatter class
import mx.formatters.Formatter
In this example, the MySimpleFormatter.as file is located in the myComponents/formatter subdirectory of the
main application directory. You map the myComponents.formatters namespace to the MyComp prefix, as the
following example shows:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="myComponents.formatters.*">
ADOBE FLEX 3 45
Creating and Extending Flex Components
<MyComp:MySimpleFormatter/>
</mx:Application>
If multiple files with the same name exist under an ActionScript classpath subdirectory and the application
subdirectory, Flex uses the file under the application subdirectory.
3 If you store the formatter component in a subdirectory of the ActionScript classpath directory, you specify that
subdirectory as part of the package statement, as the following example shows:
package flexSharedRoot.custom.components
{
//Import base Formatter class.
import mx.formatters.Formatter
You then use a namespace that specifies the subdirectory. The following code declares a component that is in the
flexSharedRoot/custom/components directory:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="flexSharedRoot.custom.components.*"/>
<MyComp:MySimpleFormatter/>
</mx:Application>
If the same file exists in the ActionScript classpath directory and the application directory, Flex uses the file in
the application file directory.
In this example, you use the following options of the compc compiler:
ADOBE FLEX 3 46
Creating and Extending Flex Components
-source-path Specifies the base directory location of the MySimpleFormatter.as file. It does not include the directories
that the component’s package statement defines.
-include-classes Specifies classes to include in the SWC file. You provide the class name (MyComponents.format-
ters.MySimpleFormatter) not the filename of the source code. All classes specified with this option must
be in the compiler's source path, which is specified in the source-path compiler option.
You can use packaged and unpackaged classes. To use components in namespaces, use the include-
namespaces option.
If the components are in packages, use dot-notation rather than slashes to separate package levels.
-o Specifies the name and directory location of the output SWC file. In this example, the directory is
c:\flex\mainApp, the directory that contains your main application.
In your main application file, you specify the component’s namespace, as the following example shows:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="myComponents.formatters.*">
<MyComp:MyFormatter/>
</mx:Application>
When you distribute SWC files, ensure that the corresponding ActionScript file is not in the directory structure of
the application or in the ActionScript classpath. Otherwise, Flex might use the ActionScript file, rather than the SWC
file.
When you use mxmlc to compile the main application, ensure that the c:\flex\mainApp directory is included in the
library path, otherwise mxmlc cannot locate the SWC file.
For more information about SWC files, see “Using the Flex Compilers” on page 109 in Building and Deploying Flex
Applications, and “Building Projects” on page 127 in Using Flex Builder.
Typically, you copy these components to a subdirectory of the WEB-INF directory for the web application that corre-
sponds to your LiveCycle Data Services ES application. For example, you can copy custom ActionScript classes and
MXML components to the WEB-INF/flex/user_classesdirectory.
Contents
About MXML components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
Scoping in custom components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
Applying styles to your custom component . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
The root tag of an MXML component is a component tag, either a Flex component or another MXML component.
The root tag specifies the http://www.adobe.com/2006/mxml namespace. For example, the following MXML
component extends the standard Flex ComboBox control.
<?xml version="1.0"?>
<!-- mxml/StateComboBox.mxml -->
<mx:ComboBox xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:dataProvider>
<mx:String>AK</mx:String>
<mx:String>AL</mx:String>
<!-- Add all other states. -->
</mx:dataProvider>
</mx:ComboBox>
As part of its implementation, a custom MXML component can reference another custom MXML component.
The main application, or any other MXML component file, references the StateComboBox component, as the
following example shows:
<?xml version="1.0"?>
<!-- mxml/MXMLMyApplication.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="*">
<MyComp:StateComboBox/>
</mx:Application>
In this example, the main application file includes a new namespace definition of xmlns:MyComp="*" as part of the
<mx:Application> tag. This namespace definition specifies the location of the MXML component. In this case, it
specifies that the component is in the same directory as the main application file or, if you are using LiveCycle Data
Services ES, in the WEB-INF/flex/user-classes directory.
As a best practice, store your components in a subdirectory. For example, you can write this file to the myCompo-
nents directory, a subdirectory of your main application directory. For more information on the namespace, see
“Developing Applications in MXML” on page 4 in Flex Developer’s Guide.
The StateComboBox.mxmlfile specifies the ComboBox control as its root tag, so you can reference all of the
properties of the ComboBox control within the MXML tag of your custom component, or in the ActionScript
specified within an <mx:Script> tag. For example, the following example specifies the rowCount property and a
listener for the close event for your custom control:
<?xml version="1.0"?>
<!-- mxml/MyApplicationProps.mxml-->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:local="*">
<mx:Script>
<![CDATA[
import flash.events.Event;
}
]]>
</mx:Script>
ADOBE FLEX 3 51
Creating and Extending Flex Components
</mx:Application>
If this tag defines a default property named default_property, the preceding tag definition is equivalent to the
following code:
<mx:SomeTag>
<default_property>
anything here
</default_property>
</mx:SomeTag>
However, the default property mechanism does not work for root tags of MXML components. In this situation, you
must use child tags to define the default property, as the following example shows:
<?xml version="1.0"?>
<mx:SomeTag xmlns:mx="http://www.adobe.com/2006/mxml">
<default_property>
anything here
</default_property>
</<mx:SomeTag>
<mx:FormItem label="NameField">
<mx:TextInput/>
</mx:FormItem>
<mx:FormItem label="Street">
<mx:TextInput/>
</mx:FormItem>
</mx:Form>
The following application file references the AddressForm component in the <AddressForm> tag:
<?xml version="1.0"?>
<!-- mxml/MyApplicationAddressForm.mxml-->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="*" >
<MyComp:AddressForm/>
</mx:Application>
If you include child tags of the root container tag in an MXML component file, you cannot add child tags when you
use the component as a custom tag in another MXML file. If you define an empty container in an MXML file, you
can add child tags when you use the component as a custom tag.
Note: The restriction on child tags refers to the child tags that correspond to visual components. Visual components are
subclasses of the UIComponent component. You can always insert tags for nonvisual components, such as ActionScript
blocks, styles, effects, formatters, validators, and other types of nonvisual components, regardless of how you define your
custom component.
The following example defines an empty Form container in an MXML component:
<?xml version="1.0"?>
<!-- mxml/EmptyForm.mxml -->
<mx:Form xmlns:mx="http://www.adobe.com/2006/mxml"/>
This component defines no children of the Form container, therefore, you can add children when you use it in
another MXML file, as the following example shows:
<?xml version="1.0"?>
<!-- mxml/MainEmptyForm.mxml-->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="*">
<MyComp:EmptyForm>
<mx:FormItem label="Name">
<mx:TextInput/>
</mx:FormItem>
</MyComp:EmptyForm>
</mx:Application>
ADOBE FLEX 3 53
Creating and Extending Flex Components
The AddressForm.mxml file specifies the Form container as its root tag. Because you define a container as the root
tag of the MXML component, you are creating a subclass of that container, and you can reference all of the properties
and methods of the root tag when using your MXML component. Therefore, in the main application, you can
reference all of the properties of the Form container in the MXML tag that corresponds to your custom component,
or in any ActionScript code in the main application. However, you cannot reference properties of the children of the
Form container.
For example, the following example sets the horizontalPageScrollSize property and a listener for the scroll
event for your custom control, but you cannot specify properties for the child CheckBox or TextInput controls of the
Form container:
<?xml version="1.0"?>
<!-- mxml/MainEmptyFormProps.mxml-->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="*">
<mx:Script>
<![CDATA[
import mx.events.ScrollEvent;
</mx:Application>
To configure the children of a custom MXML component, you define new properties in the MXML component, and
then use those new properties to pass configuration information to the component children. For more information,
see “Creating Advanced MXML Components” on page 61.
<mx:ComboBox xmlns:mx="http://www.adobe.com/2006/mxml"
close="handleCloseEvent(event);">
ADOBE FLEX 3 54
Creating and Extending Flex Components
<mx:Script>
<![CDATA[
import flash.events.Event;
<mx:dataProvider>
<mx:String>AK</mx:String>
<mx:String>AL</mx:String>
</mx:dataProvider>
</mx:ComboBox>
This example defines an event listener for the ComboBox control that updates the stateIndex property when the
ComboBox control closes.
<?xml version="1.0"?>
<!-- mxml/myComponents/StateComboBoxWithStyleProps.mxml -->
<mx:ComboBox xmlns:mx="http://www.adobe.com/2006/mxml"
openDuration="1000"
fontSize="15">
<mx:dataProvider>
<mx:Array>
<mx:String>AK</mx:String>
<mx:String>AL</mx:String>
</mx:Array>
</mx:dataProvider>
</mx:ComboBox>
Alternatively, you can define these styles by using a class selector style declaration, as the following example shows:
<?xml version="1.0"?>
<!-- mxml/myComponents/StateComboBoxWithStyleClassSel.mxml -->
<mx:Style>
.myCBStyle {
openDuration : 1000;
fontSize : 15;
}
</mx:Style>
<mx:dataProvider>
<mx:Array>
<mx:String>AK</mx:String>
<mx:String>AL</mx:String>
</mx:Array>
</mx:dataProvider>
</mx:ComboBox>
Note: You cannot define a type selector in an MXML component. If you define a type selector, a compiler error occurs.
Application developers can apply additional styles to the component. For example, if your component defines styles
for the open duration and font size, application developers can still specify font color or other styles. The following
example uses StateComboBoxWithStyleProps.mxml in an application and specifies the font color style for the
control:
<?xml version="1.0"?>
<!-- mxml/MainStyleWithPropsAddColor.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="myComponents.*">
<MyComp:StateComboBoxWithStyleProps color="red"/>
</mx:Application>
The styles that application developers can apply correspond to the styles supported by the root tag of the MXML
component. The following example uses a tag property to set a style for the custom MXML component:
<?xml version="1.0"?>
<!-- mxml/MainStyleWithPropsOverrideOpenDur.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="myComponents.*">
<MyComp:StateComboBoxWithStyleProps openDuration="1000"/>
</mx:Application>
When you specify styles as tag attributes, those styles override any conflicting styles set in the definition of the
MXML component.
You can use a class selector to define styles. Often you use a class selector to apply styles to specific instances of a
control, as the following example shows:
<?xml version="1.0"?>
<!-- mxml/MainStyleOverrideUsingClassSel.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="myComponents.*">
<mx:Style>
.myStateComboBox {
openDuration : 1000;
}
</mx:Style>
<MyComp:StateComboBoxWithStyleProps styleName="myStateComboBox"/>
<mx:ComboBox>
...
</mx:ComboBox>
</mx:Application>
In this example, you use the styleName property in the tag definition of an MXML component to apply styles to a
specific instance of the MXML component. However, those styles are not applied to the ComboBox control defined
in the main application file, nor would they be applied to any other instances of StateComboBox.mxml unless you
also specify the styleName property as part of defining those instances of the MXML component.
When you specify any styles by using a class selector, those styles override all styles that you set by using a class
selector in the MXML file. Those styles do not override styles that you set by using tag properties in the MXML file.
You can also use a type selector to define styles. A type selector applies styles to all instances of a component, as the
following example shows:
<?xml version="1.0"?>
<!-- mxml/MainStyleOverrideUsingTypeSel.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="myComponents.*">
<mx:Style>
StateComboBoxWithStyleProps {
openDuration : 1000;
}
</mx:Style>
<MyComp:StateComboBoxWithStyleProps/>
</mx:Application>
ADOBE FLEX 3 57
Creating and Extending Flex Components
In this example, the type selector specifies the openDuration style for all instances of the StateComboBox control
in the application. When you specify any styles by using a type selector, those styles override all styles that you set by
using a class selector in the MXML file. Those styles do not override styles that you set by using tag properties in the
MXML file.
<mx:Style>
ComboBox {
openDuration: 1000;
fontSize: 15;
color: red;
}
</mx:Style>
<MyComp:StateComboBoxWithStyleProps/>
<mx:ComboBox/>
</mx:Application>
In this example, all ComboBox controls and all StateComboBox.mxml controls have an openDuration of 1000 ms,
fontSize of 15 points, and red text.
If you define a type selector for a superclass of the custom control, and for the custom control itself, Flex ignores any
conflicting settings from the type selector for the superclass, as the following example shows:
<?xml version="1.0"?>
<!-- mxml/MainStyleOverrideUsingCBTypeSelConflict.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="myComponents.*">
<mx:Style>
ComboBox {
color: red;
openDuration: 1000;
fontSize: 15;
}
StateComboBoxWithStyleProps {
color: green;
}
</mx:Style>
<MyComp:StateComboBoxWithStyleProps/>
<mx:ComboBox/>
</mx:Application>
In this example, the StateComboBox control uses green text, and the values for the fontSize and openDuration
styles specified in the type selector for the ComboBox control.
ADOBE FLEX 3 58
Creating and Extending Flex Components
<mx:dataProvider>
<mx:String>AK</mx:String>
<mx:String>AL</mx:String>
<!-- Add all other states. -->
</mx:dataProvider>
</mx:ComboBox>
Notice that this control does not define any style settings.
Then you create a defaults.css file in the same directory to define the default style settings for the custom component,
as the following example shows:
StateComboBox
{
arrowButtonWidth: 40;
cornerRadius: 10;
fontSize: "14";
fontWeight: "bold";
leading: 0;
paddingLeft: 10;
paddingRight: 10;
}
To create the SWC file, you run the compc command-line utility from the directory that contains the defaults.css and
StateComboBox.mxml files. Use the include-file option to specify the style sheet, as the following example
shows:
flex_install_dir\bin\compc -source-path .
ADOBE FLEX 3 59
Creating and Extending Flex Components
-include-classes StateComboBox
-include-file defaults.css defaults.css
-o MyComponentsSWC.swc
To use the StateComboBox.mxml component in your application, you define DefaultCSSApplication.mxml as the
following example shows:
<?xml version="1.0"?>
<!-- styles/DefaultCSSApplicationSubDir.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
ADOBE FLEX 3 60
Creating and Extending Flex Components
xmlns:MyComp="myComponents.*">
Contents
About reusable MXML components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
Adding custom properties and methods to a component. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
Working with events. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
About interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
In the following example, the component defines two data providers to populate the ComboBox control, and a
function to use as the event listener for the creationComplete event. This function sets the data provider of the
ComboBox based on the value of the shortNames property. By default, the shortNames property is set to true, to
display two-letter names:
<?xml version="1.0"?>
<!-- mxmlAdvanced/myComponents/StateComboBoxPropAS.mxml -->
<mx:ComboBox xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="setNameLength();">
<mx:Script>
<![CDATA[
dataProvider=stateArrayShort; }
else {
dataProvider=stateArrayLong; }
}
]]>
</mx:Script>
</mx:ComboBox>
The following MXML application file uses the <MyComp:StateComboBoxPropAS> tag to configure the control to
display long state names:
<?xml version="1.0"?>
<!-- mxmlAdvanced/MainPropAS.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="myComponents.*">
<MyComp:StateComboBoxPropAS shortNames="true"/>
</mx:Application>
The following example modifies the component to add a method that lets you change the display of the state name
at run time. This public method takes a single argument that specifies the value of the shortNames property:
<?xml version="1.0"?>
<!-- mxmlAdvanced/myComponents/StateComboBoxPropMethod.mxml -->
<mx:ComboBox xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="setNameLength();">
<mx:Script>
<![CDATA[
</mx:Application>
All properties defined by using the <mx:String>, <mx:Number>, and <mx:Boolean> tags are public. This means
that the component user can access these properties.
The following example modifies the example in “Defining properties and methods in ActionScript” on page 62 to
define the shortNames property by using an MXML tag, rather than an ActionScript variable definition:
<?xml version="1.0"?>
<!-- mxmlAdvanced/myComponents/StateComboBoxPropMXML.mxml -->
<mx:ComboBox xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="setNameLength();">
<mx:Script>
<![CDATA[
}
]]>
</mx:Script>
</mx:ComboBox>
In the preceding example, you implement the StateComboBox.mxml file by using the <mx:Boolean> tag to add a
new property, shortNames, with a default value of true. This property controls whether the ComboBox control
displays state names that use a two-letter format, or the entire state name.
<mx:ComboBox xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
// Set method.
public function set shortNames(val:Boolean):void {
// Call method to set the dataProvider
// based on the name length.
__shortNames = val;
if (__shortNames) {
this.dataProvider=stateArrayShort; }
else {
this.dataProvider=stateArrayLong; }
}
// Get method.
public function get shortNames():Boolean{
return __shortNames;
}
]]>
</mx:Script>
</mx:ComboBox>
ADOBE FLEX 3 66
Creating and Extending Flex Components
In this example, you create a StateComboBoxGetSet.mxml control that takes a shortNames property defined by
using ActionScript setter and getter methods. One advantage to using setter and getter methods to define a property
is that the component can recognize changes to the property at run time. For example, you can give your users the
option of displaying short state names or long state names from the application. The setter method modifies the
component at run time in response to the user’s selection.
You can also define events to be dispatched when a property changes. This enables you to signal the change so that
an event listener can recognize the change. For more information on events, see “Working with events” on page 72.
You can call a component’s custom methods and access its properties in ActionScript just as you would any instance
method or component property, as the following application shows:
<?xml version="1.0"?>
<!-- mxmlAdvanced/MainPropSetGet.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="myComponents.*">
</mx:Application>
In this example, selecting the button toggles the display format of the state name between the short and long formats.
]]>
</mx:Script>
For more information on the [Inspectable] metadata tag, see “Using Metadata Tags in Custom Components” on
page 27.
Data binding is usually triggered whenever the value of the source property changes.
ADOBE FLEX 3 67
Creating and Extending Flex Components
Properties that you define in your custom controls can also take advantage of data binding. You can automatically
use any property defined by using an MXML tag, such as <mx:Boolean>, and any ActionScript property defined as
a variable or defined by using setter and getter methods as the destination of a binding expression.
For example, “Defining properties by using setters and getters” on page 65 defined the shortNames property of
StateComboBoxGetSet.mxml by using setter and getter methods. With no modification to that component, you can
use shortNames as the destination of a binding expression, as the following example shows:
<MyComp:StateComboBoxSetGet shortNames="{some_prop}"/>
However, you can also write your component to use the shortNames property as the source of a binding expression,
as the following example shows for the nex component StateComboBoxGetSetBinding.mxml:
<?xml version="1.0"?>
<!-- mxmlAdvanced/MainPropSetGetBinding.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="myComponents.*">
<mx:Button click="myStateCB.shortNames=!myStateCB.shortNames;"/>
</mx:Application>
When a property is the source of a data binding expression, any changes to the property must signal an update to the
destination property. The way to signal that change is to dispatch an event, as the following example shows:
<?xml version="1.0"?>
<!-- mxmlAdvanced/myComponents/StateComboBoxSetGetBinding.mxml -->
<mx:ComboBox xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import flash.events.Event;
</mx:ComboBox>
For more information on using the [Bindable] tag, see “Bindable metadata tag” on page 31.
Even if the calling file does not pass a reference to the Application object, you can always access it from your MXML
component. For example, the following application contains a custom component called StateComboBoxDirectRef.
In this example, StateComboBoxDirectRef is designed to write the index of the selected item in the ComboBox to
the TextArea control:
<?xml version="1.0"?>
<!-- mxmlAdvanced/MainDirectRef.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="myComponents.*">
<mx:TextArea id="myTAMain"/>
<MyComp:StateComboBoxDirectRef/>
</mx:Application>
The simplest way to write StateComboBoxDirectRef.mxml is to use the mx.core.Application.application
static property to write the index directly to the TextArea control, as the following example shows:
<?xml version="1.0"?>
<!-- mxmlAdvanced/myComponents/StateComboBoxDirectRef.mxml -->
<mx:ComboBox xmlns:mx="http://www.adobe.com/2006/mxml"
close="handleCloseEvent(event);">
<mx:Script>
<![CDATA[
import flash.events.Event;
import mx.core.Application;
<mx:dataProvider>
<mx:String>AK</mx:String>
<mx:String>AL</mx:String>
</mx:dataProvider>
</mx:ComboBox>
In the previous example, you use the close event of the ComboBox control to write the selectedIndex directly to
the TextArea control in the main application. You must cast the value of selectedIndex to a String because the text
property of the TextArea control is of type String.
You could make the custom component slightly more reusable by using the parentDocument property to reference
the TextArea control, rather than the mx.core.Application.application static property. By using the
parentDocument property, you can call the custom component from any other MXML component that contains a
TextArea control named myTAMain, as the following example shows:
<?xml version="1.0"?>
<!-- mxmlAdvanced/myComponents/StateComboBoxDirectRefParentObj.mxml -->
<mx:ComboBox xmlns:mx="http://www.adobe.com/2006/mxml"
close="handleCloseEvent(event);">
<mx:Script>
<![CDATA[
ADOBE FLEX 3 70
Creating and Extending Flex Components
import flash.events.Event;
<mx:dataProvider>
<mx:Array>
<mx:String>AK</mx:String>
<mx:String>AL</mx:String>
</mx:Array>
</mx:dataProvider>
</mx:ComboBox>
Although these examples work, they require that the TextArea control has a predefined id property, and that MXML
component knows that id. In this case, custom component is an example of a tightly coupled component. That is,
the component is written for a specific application and application structure, and it is not easily reused in another
application.
</mx:Application>
The custom component does not have to know anything about the main application, other than that it writes its
results back to a TextArea control, as the following example shows:
<?xml version="1.0"?>
<!-- mxmlAdvanced/myComponents/StateComboBoxPassRefToTA.mxml -->
<mx:Script>
<![CDATA[
import flash.events.Event;
import mx.controls.TextArea;
<mx:dataProvider>
<mx:String>AK</mx:String>
ADOBE FLEX 3 71
Creating and Extending Flex Components
<mx:String>AL</mx:String>
</mx:dataProvider>
</mx:ComboBox>
In this example, you use the Flex data binding syntax to pass the reference to the TextArea control to your custom
component. Now, you can use StateComboBoxPassRefToTA.mxml anywhere in an application. The only
requirement is that the calling component must pass a reference to a TextArea control to the component.
</mx:Application>
In the definition of DestinationComp.mxml, you define the caller property, and specify as its data type the name
of the file of the calling MXML file, as the following example shows:
<?xml version="1.0"?>
<!-- mxmlAdvanced/myComponents/DestinationComp.mxml -->
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
// Define variable to reference calling file.
[Bindable]
public var caller:CallingComponent;
]]>
</mx:Script>
<mx:Script>
<![CDATA[
import flash.events.Event;
</mx:Application>
In this example, if the MXML component dispatches a close event, the event listener in the calling MXML file
handles it.
Alternatively, you could define the event listener within the StateComboBox.mxml component, as the following
example shows:
<?xml version="1.0"?>
<!-- StateComboBox.mxml -->
<mx:ComboBox xmlns:mx="http://www.adobe.com/2006/mxml"
close="handleCloseEvent(event);">
<mx:Script>
<![CDATA[
import flash.events.Event;
<mx:dataProvider>
ADOBE FLEX 3 73
Creating and Extending Flex Components
<mx:String>AK</mx:String>
<mx:String>AL</mx:String>
</mx:dataProvider>
</mx:ComboBox>
With simple MXML components, you can define event listeners in both places, and both event listeners process the
event. However, the event listeners defined within the component execute before any listeners defined in the appli-
cation.
You dispatch new event types by using the dispatchEvent() method, as the following example shows:
<?xml version="1.0"?>
<!-- mxmlAdvanced/myComponents/TextAreaEnabled.mxml -->
<mx:Metadata>
[Event(name="enableChanged", type="flash.events.Event")]
</mx:Metadata>
<mx:Script>
<![CDATA[
import flash.events.Event;
return __enableTA;
}
]]>
</mx:Script>
</mx:TextArea>
The following main application includes TextAreaEnabled.mxml and defines an event listener for the
enableChanged event:
<?xml version="1.0"?>
<!-- mxmlAdvanced/MainTextAreaEnable.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="myComponents.*">
<mx:Script>
<![CDATA[
import flash.events.Event;
import myComponents.TextAreaEnabled;
</mx:Application>
If you do not use the [Event] metadata tag in the custom component file to define the enableChanged event, the
MXML compiler generates an error message when you reference the event name in an MXML file. Any component
can register an event listener for the event in ActionScript using the addEventListener() method, even if you omit
the [Event] metadata tag.
You can also create and dispatch events that use an event object of a type other than that defined by the Event class.
For example, you might want to create an event object that contains new properties so that you can pass those
properties back to the referencing file. To do so, you create a subclass of the Event class to define your new event
object. For information on creating custom event classes, see “Creating Custom Events” on page 20.
To handle an event that a child of the root container dispatches, you can handle it in the MXML component in the
same way as you handle an event from the root container. However, if a child component of the root container
dispatches an event, and you want that event to be dispatched to the referencing file, you must add logic to your
custom component to propagate the event.
For example, you can define a component that uses an <mx:Form> tag as the root tag, and include within it a
ComboBox control. Any event that the Form container dispatches, such a scroll event, is dispatched to the refer-
encing file of the custom component. However, the close event of the ComboBox control is dispatched only within
the custom MXML component.
To propagate the close event outside of the custom component, you define an event listener for it in the MXML
component that redispatches it, as the following example shows:
<?xml version="1.0"?>
<!-- mxmlAdvanced/myComponents/AddressForm.mxml -->
<mx:Metadata>
[Event(name="close", type="flash.events.Event")]
</mx:Metadata>
<mx:Script>
<![CDATA[
import flash.events.Event;
// Redispatch event.
private function handleCloseEventInternal(eventObj:Event):void {
dispatchEvent(eventObj);
}
]]>
</mx:Script>
<mx:FormItem label="Name">
<mx:TextInput id="name1" />
</mx:FormItem>
<mx:FormItem label="Street">
<mx:TextInput id="street" />
</mx:FormItem>
In this example, you propagate the event to the calling file. You could, alternatively, create an event type and new
event object as part the propagation. For more information on the [Event] metadata tag, see “Using Metadata Tags
in Custom Components” on page 27.
You can handle the close event in your main application, as the following example shows:
<?xml version="1.0"?>
<!-- mxmlAdvanced/MainAddressFormHandleEvent.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="myComponents.*">
<mx:Script>
<![CDATA[
import flash.events.Event;
<MyComp:AddressForm mouseDown="handleMouseDown(event);"
close="handleCloseEvent(event);"/>
</mx:Application>
About interfaces
Interfaces are a type of class that you design to act as an outline for your components. When you write an interface,
you provide only the names of public methods rather than any implementation. For example, if you define two
methods in an interface and then implement that interface, the implementing class must provide implementations
of those two methods.
Interfaces in ActionScript can only declare methods and properties by using setter and getter methods; they cannot
specify constants. The benefit of interfaces is that you can define a contract that all classes that implement that
interface must follow. Also, if your class implements an interface, instances of that class can also be cast to that
interface.
Custom MXML components can implement interfaces just as other ActionScript classes can. To do this, you use the
implements attribute. All MXML tags support this attribute.
The following code is an example of a simple interface that declares several methods:
// The following is in a file named SuperBox.as.
interface SuperBox {
function selectSuperItem():String;
function removeSuperItem():Boolean;
function addSuperItem():Boolean;
}
ADOBE FLEX 3 77
Creating and Extending Flex Components
A class that implements the SuperBox interface uses the implements attribute to point to its interface and must
provide an implementation of the methods. The following example of a custom ComboBox component implements
the SuperBox interface:
<?xml version="1.0"?>
<!-- StateComboBox.mxml -->
You can implement multiple interfaces by separating them with commas, as the following example shows:
<mx:ComboBox xmlns:mx="http://www.adobe.com/2006/mxml" implements="SuperBox, SuperBorder,
SuperData">
All methods that you declare in an interface are considered public. If you define an interface and then implement
that interface, but do not implement all of its methods, the MXML compiler throws an error.
Methods that are implemented in the custom component must have the same return type as their corresponding
methods in the interface. If no return type is specified in the interface, the implementing methods can declare any
return type.
These events are all defined by the UIComponent class, and inherited by all of its subclasses. If you create an MXML
component that is not a subclass of UIComponent, you cannot take advantage of these events. You can instead
implement the IMXMLObject interface in your MXML component, and then implement the
IMXMLObject.initialized() method, as the following example shows:
<?xml version="1.0"?>
<!-- mxmlAdvanced/myComponents/ObjectComp.mxml -->
<mx:Object xmlns:mx="http://www.adobe.com/2006/mxml"
implements="mx.core.IMXMLObject">
ADOBE FLEX 3 78
Creating and Extending Flex Components
<mx:Script>
<![CDATA[
<mx:Number id="y"/>
<mx:Number id="z"/>
<mx:Number id="x"/>
</mx:Object>
Flex calls the IMXMLObject.initialized() method after it initializes the properties of the component. The
following example uses this component:
<?xml version="1.0"?>
<!-- mxmlAdvanced/MainInitObject.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="myComponents.*"
creationComplete="initApp();">
<mx:Script>
<![CDATA[
</mx:Application>
Because Flex calls the IMXMLObject.initialized() method after it initializes the properties of the component,
the trace() function in the implementation of the IMXMLObject.initialized() method outputs the following:
initialized, x = 1
79
Contents
About ActionScript components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
Adding properties and methods to a component. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
Defining events in ActionScript components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
Applying styles to custom components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
UIComponent
VBox
Note: This example shows a portion of the class hierarchy. For a complete description of the class hierarchy, see the Adobe
Flex Language Reference.
All Flex visual components are derived from the ActionScript UIComponent class. To create your own components,
you can create a subclass from the UIComponent class, or from any of its subclasses.
ADOBE FLEX 3 81
Creating and Extending Flex Components
The class you choose to use as the superclass of your custom component depends on what you are trying to accom-
plish. For example, you might require a custom button control. You could create a subclass of the UIComponent
class, then recreate all of the functionality built into the Flex Button class. A better and faster way to create your
custom button component is to create a subclass of the Flex Button class, and then modify it in your custom class.
This topic describes how to create simple ActionScript components. Simple components are subclasses of existing
Flex components that modify the behavior of the component, or add new functionality to it. For example, you might
add a new event type to a Button control, or modify the default styles or skins of a DataGrid control.
You can also create advanced ActionScript components. Advanced ActionScript components might have one of the
following requirements:
• Modify the appearance of a control or the layout functionality of a container
• Encapsulate one or more components into a composite component
• Subclass UIComponent to create components
For information on creating advanced ActionScript components, see “Creating Advanced Visual Components in
ActionScript” on page 98.
// Constructor
public function DeleteTextArea() {
// Call super().
super();
<?xml version="1.0"?>
<!-- as/MainDeleteTextArea.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="myComponents.*">
<MyComp:DeleteTextArea/>
</mx:Application>
Note: Your class must be specified as public for you to be able to access it by using an MXML tag.
In this example, you first define the MyComp namespace to specify the location of your custom component. You then
reference the component as an MXML tag by using the namespace prefix.
You can specify any inherited properties of the superclass in MXML, as the following example shows:
<?xml version="1.0"?>
<!-- as/MainDeleteTextAreaProps.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="myComponents.*">
</mx:Application>
You do not have to change the name of your custom component when you create a subclass of a Flex class. In the
previous example, you could have named your custom component TextArea, and written it to the TextArea.as file in
the myComponents directory, as the following example shows:
package myComponents
{
import mx.controls.TextArea;
import flash.events.KeyboardEvent;
You can now use your custom TextArea control, and the standard TextArea control, in an application. To differen-
tiate between the two controls, you use the namespace prefix, as the following example shows:
<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:MyComp="myComponents.*" >
<MyComp:TextArea/>
<mx:TextArea/>
</mx:Application>
To create a component that takes tag attributes in MXML, you define a public variable with the same name as the tag
attribute in your class definition:
public class MyCustomComponent extends TextArea {
You can also use public getter and setter methods to define a property, as the following example shows:
public class MyCustomComponent extends TextArea {
You can define and initialize a private variable, as the following example shows:
private var _prop2:Number=5;
When you specify a value to the property in MXML, Flex automatically calls the setter method. If you do not set the
property in MXML, Flex sets it to its initial value, if you specified one, or to the type’s default value, which is NaN for
a variable of type Number.
// as/myComponents/TextAreaFontControl.as
import mx.controls.TextArea;
import flash.events.KeyboardEvent;
import flash.events.Event;
ADOBE FLEX 3 84
Creating and Extending Flex Components
<?xml version="1.0"?>
<!-- as/MainTextAreaFontControl.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="myComponents.*">
<MyComp:TextAreaFontControl id="myTAFS"
minFontSize="8"
maxFontSize="50"/>
<mx:Button
label="Get Font Size"
click="myTA.text=String(myTAFS.getStyle('fontSize'));"/>
<mx:TextArea id="myTA"/>
</mx:Application>
if (value!=null)
text=value;
}
<MyComp:TextAreaDefaultProp>Hello</MyComp:TextAreaDefaultProp>
</mx:Application>
The one place where Flex prohibits the use of a default property is when you use the ActionScript class as the root
tag of an MXML component. In this situation, you must use child tags to define the property, as the following
example shows:
<?xml version="1.0"?>
<!-- as/myComponents/TextAreaDefaultPropMXML.mxml -->
<MyComp:TextAreaDefaultProp xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="myComponents.*">
<MyComp:defaultText>Hello</MyComp:defaultText>
</MyComp:TextAreaDefaultProp>
You can also use the [Inspectable] metadata tag with setter and getter methods. For more information, see “Using
Metadata Tags in Custom Components” on page 27.
<mx:HSlider id="mySlider"/>
<mx:Text text="{mySlider.value}"/>
ADOBE FLEX 3 88
Creating and Extending Flex Components
The current value of the HSlider control appears in the Text control when you stop moving the slider. To get
continuous updates as you move the slider, set the HSlider.liveDragging property to true.
<MyComp:TextAreaFontControl id="myTA"
maxFontSize="{Number(myTI.text)}"/>
</mx:Application>
In this example, any value that the user enters into the TextInput control is automatically copied to the maxFontSize
property.
For more information on the [Bindable] metadata tag, see “Using Metadata Tags in Custom Components” on
page 27.
The following example modifies the component in the section “Defining public properties in ActionScript” on
page 82 to make the maxFontSize and minFontSize properties usable as the source for data bindings:
// Define public properties for tracking font size.
[Bindable]
public var maxFontSize:Number = 15;
[Bindable]
public var minFontSize:Number = 5;
ADOBE FLEX 3 89
Creating and Extending Flex Components
If you omit the event name from the [Bindable] metadata tag, Flex automatically dispatches an event named
propertyChange when the property changes to trigger the data binding. If the property value remains the same on
a write, Flex does not dispatch the event or update the property.
When you define a property by using getter and setter methods so that the property is usable as the source for data
binding, you include the [Bindable] metadata tag before the getter method, and optionally include the name of the
event dispatched by the setter method when the property changes, as the following example shows:
package myComponents
{
// as/myComponents/TextAreaFontControlBinding.as
import mx.controls.TextArea;
import flash.events.KeyboardEvent;
import flash.events.Event;
case 73 :
if (currentFontSize < maxFontSize) {
currentFontSize = currentFontSize + 1;
setStyle('fontSize', currentFontSize);
}
break;
// Was Ctrl-M pressed?
case 77 :
if (currentFontSize > minFontSize) {
currentFontSize = currentFontSize - 1;
setStyle('fontSize', currentFontSize);
}
break;
default :
break;
}
}
}
}
}
In this example, the setter updates the value of the property, and then dispatches an event to trigger an update of any
data binding destination. The name of the event is not restricted. You can use this component in an application, as
the following example shows:
<?xml version="1.0"?>
<!-- as/MainTextAreaFontControlBindingSource.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="myComponents.*">
<MyComp:TextAreaFontControlBinding id="myTA"
maxFontSize="{Number(myTI.text)}"/>
</mx:Application>
// Call super.addChild().
super.addChild(child);
return child;
}
}
}
Notice that the method implementation calls the super.addChild() method. The call to super.addChild()
causes Flex to invoke the superclass’s addChild() method to perform the operation. Your new functionality to open
the Alert box occurs after the super.addChild() method.
You might have to use super() to call the base class method before your code, after your code, or not at all. The
location is determined by your requirements. To add functionality to the method, you call super() before your code.
To replace the base class method, you do not call super() at all.
The following example uses this component in an application:
<?xml version="1.0"?>
<!-- as/MainHBoxWithAlert.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="myComponents.*">
<mx:Script>
<![CDATA[
import mx.controls.Button;
<MyComp:HBoxWithAlert id="myHBox">
</MyComp:HBoxWithAlert>
</mx:Application>
import mx.controls.TextInput;
<mx:TextInput id="myInput"/>
<mx:TextInput id="myOutput"/>
</MyComps:MyPanel>
Notice that the value of the id property for the two TextInput controls matches the variable names of the properties
defined in the MyPanel component. Therefore, Flex initializes the inherited properties with the TextInput controls
that you defined in MXML. This technique for initializing properties can be referred to as code behind.
You can use your custom component in the following Flex application:
<?xml version="1.0"?>
<!-- as/MainCodeBehindExample.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComps="myComponents.*">
<MyComps:MyPanelComponent id="myP"/>
</mx:Application>
If the value of the id property of a TextInput control does not match an inherited property name, Flex creates a
property of the component, where the id property defines the name of the new property.
To support initialization from MXML, an inherited property must have the following characteristics:
1 The inherited property must be public.
If you try to initialize a non-public inherited property, the Flex compiler issues an error.
2 The inherited property must be writable.
If you try to initialize a constant, or a property defined by a getter method without a corresponding setter
method, the Flex compiler issues an error.
ADOBE FLEX 3 93
Creating and Extending Flex Components
3 The data type of the value that you specify to the inherited property must by compatible with the data type of the
property.
If you try to initialize a property with a value of an incompatible data type, the Flex compiler issues an error.
<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:MyComp="myComponents.*">
<mx:Script>
<![CDATA[
import flash.events.Event;
]]>
</mx:Script>
<MyComp:MyButton
click="handleClick(event);"
creationComplete="handleCreationComplete(event);"/>
</mx:Application>
Your custom components can also define new events based on the requirements of your components. For example,
the section “Using data binding with custom properties” on page 87 showed how to define a custom event so that
properties of your component can work with the Flex data binding mechanism.
This section describes how to handle events within a custom component and how to create events for it.
Your custom component can also define event listeners within the component itself to handle the events internally.
For example, “Defining public properties as variables” on page 83 defined event listeners for the keyDown and
creationComplete events within the body of the component. This allows the component to handle those events
internally.
Note: Even though you define event listeners for the events in the component itself, your application can also register
listeners for those events. The event listeners defined within the component execute before any listeners defined in the
application.
The example used the creationComplete event to access the default fontSize property of the component. You
could not access this property in the constructor itself because Flex does not define it until after the component is
created. For more information on the initialization order of a component, see “Creating Advanced Visual Compo-
nents in ActionScript” on page 98.
// Dispatch event.
dispatchEvent(new Event("enableChanged"));
}
}
}
In this example, the public method enableInput() lets the user enable or disable input to the control. When you
call the enableInput() method, the component uses the dispatchEvent() method to dispatch the
enableChanged event. The dispatchEvent() method has the following signature:
dispatchEvent(eventObj)
The eventObj argument is the event object that describes the event.
If you want an MXML component to be able to register a listener for the event, you must make the event known to
the Flex compiler by using the [Event] metadata tag. For each public event that your custom component dispatches,
you add an [Event] metadata keyword before the class definition that defines that event; for example:
[Event(name="enableChanged", type="flash.events.Event")]
public class ModalText extends TextArea {
...
}
If you do not identify an event in the class file with the [Event] metadata tag, the compiler generates an error when
an MXML component attempts to register a listener for that event. Any component can register an event listener for
the event in ActionScript using the addEventListener() method, even if you omit the [Event] metadata tag.
You can then handle the event in MXML, as the following example shows:
<?xml version="1.0"?>
<!-- as/ASMainModalTextEvent.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComps="myComponents.*">
<mx:Script>
<![CDATA[
import flash.events.Event;
<MyComps:ModalTextEvent id="myMT"
enableChanged="handleEnableChanged(event);"/>
<mx:Button click="myMT.enableInput(true);"/>
<mx:TextArea id="myTA"/>
</mx:Application>
To change style properties in custom components, use the setStyle() method in the component’s constructor. This
applies the same style to all instances of the component, but users of the component can override the settings of the
setStyle() method in MXML tags. Any style properties that are not set in the component’s class file are inherited
from the component’s superclass.
The following ActionScript class file sets the color and borderColor styles of the BlueButton control:
package myComponents
{
// as/myComponents/BlueButton.as
import mx.controls.Button;
<MyComps:BlueButton label="Submit"/>
</mx:Application>
Setting the styles in constructor does not prevent users of the component from changing the style. For example, the
user could still set their own value for the color style, as the following example shows:
<?xml version="1.0"?>
<!-- as/MainBlueButtonRed.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComps="myComponents.*">
</mx:Application>
In addition to setting the color property, you can set the font face, font size, and other style properties. For more
information on the available style properties, see Flex Developer’s Guide.
You can also define new style properties for your components. For more information, see “Creating Advanced Visual
Components in ActionScript” on page 98.
For more information, see “Applying styles from a defaults.css file” on page 58.
98
Contents
About creating advanced components. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
Implementing the component. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
Making components accessible. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
Adding version numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
Best practices when designing a component. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
Example: Creating a composite component . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
Troubleshooting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
commitProperties() Commits any changes to component properties, either to make the changes occur at the same time, or to
ensure that properties are set in a specific order.
For more information, see “Implementing the commitProperties() method” on page 105.
createChildren() Creates any child components of the component. For example, the ComboBox control contains a TextInput
control and a Button control as child components.
For more information, see “Implementing the createChildren() method” on page 104.
layoutChrome() Defines the border area around the container for subclasses of the Container class.
For more information, see “Implementing the layoutChrome() method” on page 111.
measure() Sets the default size and default minimum size of the component.
For more information, see “Implementing the measure() method” on page 108.
updateDisplayList() Sizes and positions the children of the component on the screen based on all previous property and style
settings, and draws any skins or graphic elements used by the component. The parent container for the
component determines the size of the component itself.
For more information, see “Implementing the updateDisplayList() method” on page 111.
Component users do not call these methods directly; Flex calls them as part of the initialization process of creating
a component, or when other method calls occur. For more information, see “About the component instantiation life
cycle” on page 100.
Your application can programmatically change the font size of a component much faster than Flex can update the
layout of an application. Therefore, you only want to update the layout after you are sure that you determined the
final value of the font size.
In another scenario, when you set multiple properties of a component, such as the label and icon properties of a
Button control, you want the commitProperties(), measure(), and updateDisplayList() methods to execute
only once, after all properties are set. You do not want these methods to execute when you set the label property,
and then execute again when you set the icon property.
Also, several components might change their font size at the same time. Rather than updating the application layout
after each component changes its font size, you want Flex to coordinate the layout operation to eliminate any
redundant processing.
Flex uses an invalidation mechanism to synchronize modifications to components. Flex implements the invalidation
mechanism as a set of methods that you call to signal that something about the component has changed and requires
Flex to call the component’s commitProperties(), measure(), layoutChrome(), or updateDisplayList()
methods.
The following table describes the invalidation methods:
ADOBE FLEX 3 100
Creating and Extending Flex Components
invalidateProperties() Marks a component so that its commitProperties() method gets called during the next screen
update.
invalidateSize() Marks a component so that its measure() method gets called during the next screen update.
invalidateDisplayList() Marks a component so that its layoutChrome() and updateDisplayList() methods get called
during the next screen update.
When a component calls an invalidation method, it signals to Flex that the component must be updated. When
multiple components call invalidation methods, Flex coordinates updates so that they all occur together during the
next screen update.
Typically, component users do not call the invalidation methods directly. Instead, they are called by the component’s
setter methods, or by any other methods of a component class as necessary. For more information and examples, see
“Implementing the commitProperties() method” on page 105.
The following steps show what occurs when you execute the code to create the Button control, and add the control
to the Box container:
1 You call the component’s constructor, as the following code shows:
// Create a Button control.
var b:Button = new Button()
2 You configure the component by setting its properties, as the following code shows:
// Configure the button control.
b.label = "Submit";
3 You call the addChild() method to add the component to its parent, as the following code shows:
// Add the Button control to the Box container.
boxContainer.addChild(b);
a Sets the parent property for the component to reference its parent container.
b Computes the style settings for the component.
c Dispatches the preinitialize event on the component.
d Calls the component’s createChildren() method.
e Calls the invalidateProperties(), invalidateSize(), and invalidateDisplayList() methods to
trigger later calls to the commitProperties(), measure(), or updateDisplayList() methods during the next
render event.
The only exception to this rule is that Flex does not call the measure() method when the user sets the height
and width of the component.
f Dispatches the initialize event on the component. At this time, all of the component’s children are
initialized, but the component was not sized or processed for layout. You can use this event to perform additional
processing of the component before it is laid out.
g Dispatches the childAdd event on the parent container.
h Dispatches the initialize event on the parent container.
4 During the next render event, Flex performs the following actions:
a Calls the component’s commitProperties() method.
b Calls the component’s measure() method.
c Calls the component’s layoutChrome() method.
d Calls the component’s updateDisplayList() method.
e Dispatches the updateComplete event on the component.
5 Flex dispatches additional render events if the commitProperties(), measure(), or updateDisplayList()
methods call the invalidateProperties(), invalidateSize(), or invalidateDisplayList() methods.
6 After the last render event occurs, Flex performs the following actions:
a Makes the component visible by setting the visible property to true.
b Dispatches the creationComplete event on the component. The component is sized and processed for
layout. This event is only dispatched once when the component is created.
c Dispatches the updateComplete event on the component. Flex dispatches additional updateComplete
events whenever the layout, position, size, or other visual characteristic of the component changes and the
component is updated for display.
Most of the work for configuring a component occurs when you add the component to a container by using the
addChild() method. That is because until you add the component to a container, Flex cannot determine its size, set
inheriting style properties, or draw it on the screen.
You can also define your application in MXML, as the following example shows:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Box>
<mx:Button label="Submit"/>
</mx:Box>
</mx:Application>
The sequence of steps that Flex executes when creating a component in MXML are equivalent to the steps described
for ActionScript.
ADOBE FLEX 3 102
Creating and Extending Flex Components
You can remove a component from a container by using the removeChild() method. If there are no references to
the component, it is eventually deleted from memory by the garbage collection mechanism of Adobe Flash Player 9.
About interfaces
Flex uses interfaces to divide the basic functionality of components into discrete elements so that they can be imple-
mented piece by piece. For example, to make your component focusable, it must implement the IFocusable interface;
to let it participate in the layout process, it must implement ILayoutClient interface.
ADOBE FLEX 3 103
Creating and Extending Flex Components
To simplify the use of interfaces, the UIComponent class implements all of the interfaces defined in the following
table, except for the IFocusManagerComponent and IToolTipManagerClient interfaces. However, many subclasses
of UIComponent implement the IFocusManagerComponent and IToolTipManagerClient interfaces.
Therefore, if you create a subclass of the class or subclass of UIComponent, you do not have to implement these inter-
faces. But, if you create a component that is not a subclass of UIComponent, and you want to use that component in
Flex, you might have to implement one or more of these interfaces.
Note: For Flex 2, Adobe recommends that all of your components extend the UIComponent class or a class that extends
UIComponent.
The following table lists the main interfaces implemented by Flex components:
Interface Use
IFocusManagerComponent Indicates that a component or object is focusable, which means that the components can
receive focus from the FocusManager.
The UIComponent class does not implement IFocusable because some components are
not intended to receive focus.
IInvalidating Indicates that a component or object can use the invalidation mechanism to perform
delayed, rather than immediate, property commitment, measurement, and drawing or
layout.
ILayoutManagerClient Indicates that a component or object can participate in the LayoutManager's commit,
measure, and update sequence.
IRepeaterClient Indicates that a component or object can be used with the Repeater class.
IStyleClient Indicates that the component can inherit styles from another object, and supports the
setStyle() and getStyle() methods.
IToolTipManagerClient Indicates that a component has a toolTip property, and, therefore, is monitored by the
ToolTipManager.
IUIComponent Defines the basic set of APIs that you must implement in order to be a child of layout
containers and lists.
IValidatorListener Indicates that a component can listen for validation events, and, therefore, show a valida-
tion state, such as a red border and error tooltips.
You must define your ActionScript custom components within a package. The package reflects the directory location
of your component within the directory structure of your application.
The class definition of your component must be prefixed by the public keyword. A file that contains a class
definition can have one, and only one, public class definition, although it can have additional internal class defini-
tions. Place any internal class definitions at the bottom of your source file below the closing curly brace of the
package definition.
You do not call the createChildren() method directly; Flex calls it when the call to the addChild() method
occurs to add the component to its parent. Notice that the createChildren() method has no invalidation method,
which means that you do not have to call it a second time after the component is added to its parent.
For example, you might define a new component that consists of a Button control and a TextArea control, where the
Button control enables and disables user input to the TextArea control. The following example creates the TextArea
and Button controls:
// Declare two variables for the component children.
private var text_mc:TextArea;
private var mode_mc:Button;
Notice in this example that the createChildren() method calls the addChild() method to add the child
component. You must call the addChild() method for each child object.
After you create a child component, you can use properties of the child component to define its characteristics. In
this example, you create the Button and TextArea controls, initialize them, and register event listeners for them. You
could also apply skins to the child components. For a complete example, see “Example: Creating a composite
component” on page 115.
Calls to the commitProperties() method occur before calls to the measure() method. This lets you set property
values that the measure() method might use.
The typical pattern that you use for defining component properties is to define the properties by using getter and
setter methods, as the following example shows:
// Define a private variable for the alignText property.
private var _alignText:String = "right";
As you can see in this example, the setter method modifies the property, calls the invalidateProperties() and
invalidateDisplayList() methods, then returns. The setter itself does not perform any calculations based on the
new property value. This design lets the setter method return quickly, and leaves any processing of the new value to
the commitProperties() method.
Changing the alignment of text in a control does not necessarily change the control’s size. However, if it does, include
a call to the invalidateSize() method to trigger the measure() method.
The main advantages of using the commitProperties() method are the following:
1 To coordinate the modifications of multiple properties so that the modifications occur synchronously.
For example, you might define multiple properties that control the text displayed by the component, such as the
alignment of the text within the component. A change to either the text or the alignment property requires Flex
to update the appearance of the component. However, if you modify both the text and the alignment, you want
Flex to perform any calculations for sizing or positioning the component once, when the screen updates.
ADOBE FLEX 3 107
Creating and Extending Flex Components
Therefore, you use the commitProperties() method to calculate any values based on the relationship of
multiple component properties. By coordinating the property changes in the commitProperties() method,
you can reduce unnecessary processing overhead.
2 To coordinate multiple modifications to the same property.
You do not necessarily want to perform a complex calculation every time a user updates a component property.
For example, users modify the icon property of the Button control to change the image displayed in the button.
Calculating the label position based on the presence or size of an icon can be a computationally expensive
operation that you want to perform only when necessary.
To avoid this behavior, you use the commitProperties() method to perform the calculations. Flex calls the
commitProperties() method when it updates the display. That means you perform the calculations once when
Flex updates the screen, regardless of the number of times the property changed between screen updates.
The following example shows how you can handle two related properties in the commitProperties() method:
// Define a private variable for the text property.
private var _text:String = "ModalText";
private var bTextChanged:Boolean = false;
bAlignTextChanged = false;
In a subclass of an existing component, you might implement the measure() method only if you are performing an
action that requires modification to the default sizing rules defined in the superclass. Therefore, to set a new default
size, or perform calculations at run time to determine component sizing rules, implement the measure() method.
You set the following properties in the measure() method to specify the default size:
measuredHeight Default height and Specifies the default height and width of the component, in pixels.
measuredWidth width
These properties are set to 0 until the measure() method executes. Although you
can leave them set to 0, it makes the component invisible by default.
measuredMinHeight Default minimum Specifies the default minimum height and minimum width of the component, in
measuredMinWidth height and width pixels. Flex cannot set the size of a component smaller than its specified minimum
size.
ADOBE FLEX 3 109
Creating and Extending Flex Components
The measure() method only sets the default size of the component. In the updateDisplayList() method, the
parent container of the component passes to it its actual size, which may be different than the default size.
Component users can also override the default size settings in an application by using the component in the
following ways:
• Setting the explicitHeight and exlicitWidth properties
• Setting the width and height properties
• Setting the percentHeight and percentWidth properties
For example, you can define a Button control with a default size of 100 pixels wide and 50 pixels tall, and a default
minimum size of 50 pixels by 25 pixels, as the following example shows:
package myComponents
{
// asAdvanced/myComponents/DeleteTextArea.as
import mx.controls.Button;
measuredWidth=100;
measuredMinWidth=50;
measuredHeight=50;
measuredMinHeight=25;
}
}
}
The following application uses this button in an application:
<?xml version="1.0"?>
<!-- asAdvanced/ASAdvancedMainBlueButton.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="myComponents.*" >
<mx:VBox>
<MyComp:BlueButton/>
<mx:Button/>
</mx:VBox>
</mx:Application>
In the absence of any other sizing constraints on the button, the VBox container uses the default size and default
minimum size of the button to calculate its size at run time. For information on the rules for sizing a component, see
“Introducing Containers” on page 413 in Flex Developer’s Guide.
You can override the default size settings in an application, as the following example shows:
<?xml version="1.0"?>
<!-- asAdvanced/MainBlueButtonResize.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="myComponents.*" >
<mx:VBox>
<MyComp:BlueButton width="50%"/>
ADOBE FLEX 3 110
Creating and Extending Flex Components
<mx:Button/>
</mx:VBox>
</mx:Application>
In this example, you specify that the width of the button is 50% of the width of the VBox container. When 50% of
the width of the container is smaller than the minimum width of the button, the button uses its minimum width.
// The default size is the size of the text plus a 10 pixel margin.
override protected function measure():void {
super.measure();
<MyComp:MyTextArea id="myTA" text="This is a long text strring that would normally cause
a TextArea control to display scroll bars. But, the custom MyTextArea control calcualtes its
default size based on the text size."/>
ADOBE FLEX 3 111
Creating and Extending Flex Components
<mx:TextArea id="flexTA" text="This is a long text strring that would normally cause a
TextArea control to display scroll bars. But, the custom MyTextArea control calcualtes its
default size based on the text size."/>
</mx:Application>
The primary reason for dividing the handling of the content area of a container from its border area is to handle the
situation when the Container.autoLayout property is set to false. When the autoLayout property is set to true,
measurement and layout of the container and of its children are done whenever the position or size of a container
child changes. The default value is true.
When the autoLayout property is set to false, measurement and layout are done only once, when children are
added to or removed from the container. However, Flex executes the layoutChrome() method in both cases.
Therefore, the container can still update its border area even when the autoLayout property is set to false.
The Button.updateDisplayList() method uses the settings of the icon and labelPlacement properties to
control the display of the button.
For containers that have child controls, the updateDisplayList() method controls how those child compo-
nents are positioned. For example, the updateDisplayList() method on the HBox container positions its
children from left to right in a single row; the updateDisplayList() method for a VBox container positions
its children from top to bottom in a single column.
To size components in the updateDisplayList() method, you use the setActualSize() method, not the
sizing properties, such as width and height. To position a component, use the move() method, not the x and
y properties.
super.updateDisplayList(unscaledWidth, unscaledHeight);
<MyComp:BottomUpVBox>
<mx:Label text="Label 1"/>
<mx:Button label="Button 1"/>
</MyComp:BottomUpVBox>
</mx:Application>
super.updateDisplayList(unscaledWidth, unscaledHeight);
For example, the following line enables accessibility for the MyButton component:
mx.accessibility.MyButton.enableAccessibility();
For additional information about accessibility, see “Creating Accessible Applications” on page 1016 in Flex
Developer’s Guide.
ADOBE FLEX 3 115
Creating and Extending Flex Components
Note: Flex does not use or interpret the value of the version property.
If you create many components as part of a component package, you can include the version number in an external
file. That way, you update the version number in only one place. For example, the following code imports the
contents of an external file that stores the version number in one place:
include "../myPackage/ComponentVersion.as"
The contents of the ComponentVersion.as file are identical to the previous variable declaration, as the following
example shows:
static var version:String = "1.0.0.42";
Properties of the individual controls are not accessible from the MXML author’s environment unless you design your
class to allow this. For example, if you create a component that extends the UIComponent class and uses a Button
and a TextArea component, you cannot set the Button control’s label text in the MXML tag because you do not
directly extend the Button class.
The createChildren() method also contains a call to the addEventListener() method to register an event
listener for the change event generated by the TextArea control, and for the click event for the Button control.
These event listeners are defined within the ModalText class, as the following example shows:
// Handle events that are dispatched by the children.
private function handleChangeEvent(eventObj:Event):void {
dispatchEvent(new Event("change"));
}
You can handle an event dispatched by a child of a composite component in the component. In this example, the
event listener for the Button control’s click event is defined in the class definition to toggle the editable property
of the TextArea control.
However, if a child component dispatches an event, and you want that opportunity to handle the event outside of the
component, you must add logic to your custom component to propagate the event. Notice that the event listener for
the change event for the TextArea control propagates the event. This lets you handle the event in your application,
as the following example shows:
ADOBE FLEX 3 117
Creating and Extending Flex Components
<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:MyComp="myComponents.*">
<mx:Script>
<![CDATA[
import flash.events.Event;
function handleText(eventObj:Event)
{
...
}
]]>
</mx:Script>
<MyComp:ModalText change="handleText(event);"/>
</mx:Application>
<?xml version="1.0"?>
<!-- asAdvanced/ASAdvancedMainModalText.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="myComponents.*" >
<MyComp:ModalText textPlacement="left"/>
</mx:Application>
You can handle the placementChanged event to determine when the ModalText.textPlacement property is
modified, as the following example shows:
ADOBE FLEX 3 118
Creating and Extending Flex Components
<?xml version="1.0"?>
<!-- asAdvanced/ASAdvancedMainModalTextEvent.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="myComponents.*" >
<mx:Script>
<![CDATA[
import flash.events.Event;
</mx:Application>
The following example shows the ModalText.as file that defines this control:
package myComponents
{
// Import all necessary classes.
import mx.core.UIComponent;
import mx.controls.Button;
import mx.controls.TextArea;
import flash.events.Event;
import flash.text.TextLineMetrics;
[Embed(source="Modal2.swf", symbol="blueCircle")]
public var modeOverSkinName:Class;
[Embed(source="Modal2.swf", symbol="greenSquare")]
public var modeDownSkinName:Class;
if (bTextChanged) {
bTextChanged = false;
text_mc.text = _text;
invalidateDisplayList();
}
}
mode_mc.move(4, 4);
text_mc.move(4 + buttonWidth + 5, 4);
}
[Bindable(event="textChanged")]
public function get text():String {
return text_mc.text;
}
Troubleshooting
This section describes some common problems and their solutions when you create components for Flex in Flash.
I get an error “don't know how to parse…” when I try to use the component from MXML.
This means that the compiler could not find the SWC file, or the contents of the SWC file did not list the component.
Ensure that the SWC file is in a directory that Flex searches, and ensure that your xmlns property is pointing to the
right place. Try moving the SWC file to the same directory as the MXML file and setting the namespace to "*" as the
following example shows:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="*">
For more information, see “Using the Flex Compilers” on page 109 in Building and Deploying Flex Applications.
I get an error “xxx is not a valid attribute…” when I try to use the component from MXML.
Ensure that the attribute is spelled correctly. Also ensure that it is not private.
I don't get any errors, but nothing appears.
Verify that the component was instantiated. One way to do this is to put a Button control and a TextArea control in
the MXML application and set the text property to the ID for the component when the button is clicked; for
example:
<!-- This verifies whether a component was instantiated. -->
<zz:mycomponent id="foo"/>
<mx:TextArea id="output"/>
<mx:Button label="Print Output" click="output.text = foo.id;"/>
In some cases, helper classes are not ready by the time your component requires them. Flex adds classes to the appli-
cation in the order that they must be initialized (base classes, and then child classes). However, if you have a static
method that gets called as part of the initialization of a class, and that static method has class dependencies, Flex does
not know to place that dependent class before the other class, because it does not know when that method is going
to be called.
One possible remedy is to add a static variable dependency to the class definition. Flex knows that all static variable
dependencies must be ready before the class is initialized, so it orders the class loading correctly.
The following example adds a static variable to tell the linker that class A must be initialized before class B:
public class A {
public class B {
static function bar():Number {
return mx.example.A.foo();
}
Verify that the measuredWidth and measuredHeight properties are nonzero. If they are zero or NaN, ensure that
you implemented the measure() method correctly.
You can also verify that the visible property is set to true. If visible=false, ensure that your component called
the invalidateDisplayList() method.
The component is instantiated properly but does not appear (3) .
It is possible that there is another class or SWC file that overrides your custom class or the symbols used in your
component. Ensure that there are no naming conflicts.
124
Contents
About styles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
Example: Creating style properties. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
About styles
You modify the appearance of Flex components through style properties. These properties can define the size of a
font used in a Label control, or the background color used in the Tree control. In Flex, some styles are inherited from
parent containers to their children, and across style types and classes. This means that you can define a style once,
and then have that style apply to all controls of a single type or to a set of controls. Also, you can override individual
properties for each control at a local, document, or global level, giving you great flexibility in controlling the
appearance of your applications.
For more information, see “Using Styles and Themes” on page 553 in Flex Developer’s Guide.
<mx:Style>
TextArea {backgroundColor: "0x0000FF"}
</mx:Style>
<mx:TextArea/>
</mx:Application>
You can also import an external CSS file, as the following example shows:
<mx:Style source="myStyle.css"/>
super.styleChanged(styleProp);
}
}
The styleChanged() method first calls superclass’s styleChanged() method to let the superclass handle the style
change.
After the superclass gets a call to handle the style change, your component can detect that the user set the
backgroundColor style, and handle it. By handling the style change after the superclass makes the change, you can
override the way the superclass handles the style.
Notice that the method calls the invalidateDisplayList() method, which causes Flex to execute the
component’s updateDisplayList() method at the next screen update. Although you can detect style changes in
the styleChanged() method, you still use the updateDisplayList() method to draw the component on the
screen. For more information, see “Defining a style property” on page 127.
Typically, you use a flag to indicate that a style changed. In the updateDisplayList() method, you check the flag
and update the component based on the new style setting, as the following example shows:
override protected function updateDisplayList(unscaledWidth:Number,
unscaledHeight:Number):void {
super.updateDisplayList(unscaledWidth, unscaledHeight);
By using flags to signal style updates to the updateDisplayList() method, the updateDisplayList() method
has to perform only the updates based on the style changes; it may not have to redraw or recalculate the appearance
of the entire component. For example, if you are changing only the border color of a component, it is more efficient
to redraw only the border, rather than redrawing the entire component every time someone changes a style.
This gradient is defined by two colors that you set by using a new style property called fillColors. The
fillColors style takes an array of two colors that component users can set. The StyledRectangle.as class defines
default colors for the fillColors style, but you can also set them as the following example shows:
<?xml version="1.0"?>
<!-- skinstyle\MainRectWithFillStyles.mxml -->
ADOBE FLEX 3 127
Creating and Extending Flex Components
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="myComponents.*">
<!-- By default, use the style defined by the CSS type selector. -->
<MyComp:StyledRectangle id="mySR1"/>
<!-- By default, use the style defined by the CSS type selector. -->
<MyComp:StyledRectangle id="mySR2"/>
<!-- Change the default style by using the setStyle() method. -->
<mx:Button label="Set gradient"
click="mySR2.setStyle('fillColors', [0x000000, 0xFFFFFF]);"/>
</mx:Application>
In this example, the CSS type selector for the StyledRectangle component sets the initial values of the fillColors
property to #FF00FF and #00FFFF. For the second StyledRectangle components, you use the click event of a Button
control to change the fillColor style by using the setStyle() method. The third component sets the style
property by using an MXML tag attribute.
For more information, see “Using Metadata Tags in Custom Components” on page 27.
2 Override the styleChanged() method to detect changes to the property.
3 Override updateDisplayList() method to incorporate the style into the component display.
4 Define a static initializer to set the default value of the style property.
For more information, see “Setting default style values” on page 129.
The following code example defines the StyledRectangle component and the fillColors style:
package myComponents
{
// skinstyle/myComponents/StyledRectangle.as
import mx.core.UIComponent;
import mx.styles.CSSStyleDeclaration;
import mx.styles.StyleManager;
ADOBE FLEX 3 128
Creating and Extending Flex Components
import flash.display.GradientType;
// Constructor
public function StyledRectangle() {
super();
}
super.styleChanged(styleProp);
}
}
<?xml version="1.0"?>
<!-- skinstyle\MainRectNoStyles.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="myComponents.*">
<MyComp:StyledRectangle/>
</mx:Application>
If you include the <mx:Style> tag, the <mx:Style> tag creates the default style definition, as the following example
shows:
ADOBE FLEX 3 130
Creating and Extending Flex Components
<?xml version="1.0"?>
<!-- skinstyle\MainRectCSSStyles.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="myComponents.*">
<mx:Style>
StyledRectangle {fillColors: #FF00FF, #00FFFF}
</mx:Style>
<MyComp:StyledRectangle/>
</mx:Application>
The one difference when defining a style property for a skin is how you specify the [Style] metadata tag. When the
style property corresponds to a skin, you specify Class as the value to the type property of the metadata tag, as the
following example shows:
[Style(name="downSkin", type="Class", inherit="no")]
For more information on creating skins, see “Creating Skins” on page 629 in Flex Developer’s Guide.
131
Contents
About template components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
Implementing a template component . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
<MyComp:MyTemplateComponent id="myTComp1">
<MyComp:topRow>
<mx:Label text="top component"/>
</MyComp:topRow>
<MyComp:bottomRow>
<mx:Button label="Button 1"/>
<mx:Button label="Button 2"/>
<mx:Button label="Button 3"/>
</MyComp:bottomRow>
</MyComp:MyTemplateComponent>
ADOBE FLEX 3 132
Creating and Extending Flex Components
</mx:Panel>
</mx:Application>
The MyTemplateComponent takes two properties:
• The topRow property specifies the single Flex component that appears in the top row of the VBox container.
• The bottomRow property specifies one or more Flex components that appear along the bottom row of the VBox
container.
The implementation of the MyTemplateComponent consists of a VBox container that displays its children in two
rows. The following image shows the output of this application:
The implementation of the topRow and bottomRow properties lets you specify any Flex component as a value, as the
following example shows:
<?xml version="1.0"?>
<!-- templating/MainTemplateLink.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="myComponents.*"
height="700" width="700">
<MyComp:MyTemplateComponent id="myTComp2">
<MyComp:topRow>
<mx:TextArea text="top component"/>
</MyComp:topRow>
<MyComp:bottomRow>
<mx:LinkButton label="Link 1"/>
<mx:LinkButton label="Link 2"/>
<mx:LinkButton label="Link 3"/>
</MyComp:bottomRow>
</MyComp:MyTemplateComponent>
</mx:Panel>
</mx:Application>
In this example, the top component is a TextArea control, and the bottom components are two LinkButton controls.
<mx:Script>
<![CDATA[
import mx.containers.HBox;
import mx.core.UIComponent;
You can create a template component that also takes advantage of deferred creation. Rather than having Flex create
your component and its properties when the application loads, you can define a component that only creates its
properties when a user navigates to the area of the application that uses the component. This is especially useful for
large components that may have many child components. Flex view states makes use of this feature.
The following example shows an alternative implementation for the MyTemplateComponent component shown in
the section “About template components” on page 131, named MyTemplateComponentDeferred.mxml, by defining
the topRow and bottomRow properties to be of type IDeferredInstance:
<?xml version="1.0"?>
<!-- templating/myComponents/MyTemplateComponentDeferred.mxml -->
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml"
initialize="init();">
<mx:Script>
<![CDATA[
import mx.containers.HBox;
import mx.core.UIComponent;
You can pass any data type to a property of type IDeferredInstance. In the example in the section “About template
components” on page 131, you pass a Label control to the topRow property, and three Button controls to the
bottomRow property.
Notice in the example that the addChild() methods that take topRow and bottomRow as arguments cast them to
UIComponent. This cast is necessary because the addChild() method can only add an object that implements the
IUIComponent interface to a container; and the DeferredInstance.getInstance() method returns a value of
type Object.
The user of the component can then specify an object of any type to the property. It is your responsibility in the
component implementation to verify that the value passed by the user is of the correct data type.
The Flex compiler validates that users only assign values of the specified type to the property. In this example, if the
component user sets the topRow property to a value of a type other than mx.controls.Label, the compiler issues an
error message.
In the first example, you can assign a value of any data type to the bottomRow property. Each array element's
getInstance() method is not called until the element is used.
In the second example, you can only assign values of type mx.controls.Button to it. Each Array element is created
when the application loads. The following template component shows an alternative implementatin of the MyTem-
plateComponent that restricts the type of components to be of type mx.controls.Button:
<?xml version="1.0"?>
<!-- templating/myComponents/MyTemplateComponentDeferredSpecific.mxml -->
ADOBE FLEX 3 136
Creating and Extending Flex Components
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml"
initialize="init();">
<mx:Script>
<![CDATA[
import mx.containers.HBox;
import mx.core.UIComponent;
[InstanceType("mx.controls.Label")]
public var topRow:IDeferredInstance;
addChild(controlHBox);
}
]]>
</mx:Script>
</mx:VBox>
137
Contents
Creating a custom formatter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
Using the SwitchSymbolFormatter class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
Extending a Formatter class. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
Formatter
Like standard formatter classes, your custom formatter class must contain a public format() method that takes a
single argument and returns a String that contains the formatted data. Most of the processing of your custom
formatter occurs within the format() method.
Your custom formatter also might let the user specify which pattern formats the data. Where applicable, the Flex
formatters, such as the ZipCodeFormatter, use a formatString property to pass a format pattern. Some Flex
formatters, such as the NumberFormatter and CurrencyFormatter classes, do not have formatString properties,
because they use a set of properties to configure formatting.
// Constructor
public function SimpleFormatter() {
// Call base class constructor.
super();
}
// Override format().
override public function format(value:Object):String {
// 1. Validate value - must be a nonzero length string.
if( value.length == 0)
{ error="0 Length String";
return ""
}
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="myFormatters.*">
<!-- Trigger the formatter while populating a string with data. -->
<mx:TextInput id="myTI" />
</mx:Application>
The namespace declaration in the <mx:Application> tag specifies to use the MyComp prefix when referencing the
formatter, and the location of the formatter’s ActionScript file. That file is in the myFormatters subdirectory of the
application, or in the default classpath of the application. For more information on deploying your formatters, see
“Compiling Components” on page 40.
ADOBE FLEX 3 140
Creating and Extending Flex Components
The SwitchSymbolFormatter class parses the format string and replaces each placeholder character with a number
from the input string in the order in which the numbers are specified in the input string. The default placeholder
character is the number sign (#). You can define a different placeholder character by passing it to the constructor
when you create a SwitchSymbolFormatter object. For an example, see “Using a different placeholder character” on
page 140.
The SwitchSymbolFormatter class creates the following output string from the Format and Input strings:
"The SocialSecurity number is: 123-45-6789"
You use the formatString property of the SwitchSymbolFormatter class to specify the format string. You can mix
alphanumeric characters and placeholder characters in this format string. The format string can contain any
characters that are constant for all values of the numeric portion of the string. However, the input string for
formatting must be numeric.
The number of digits supplied in the source value must match the number of digits defined in the format string. The
code that calls the SwitchSymbolFormatter object verifies that the number of digits match.
// Constructor
public function CustomSSFormatter() {
// Call base class constructor.
super();
}
// Override format().
override public function format( value:Object ):String {
// Validate input string value - must be a 9-digit number.
// You must explicitly check if the value is a number.
// The formatter does not do that for you.
if( !value || value.toString().length != 9)
{ error="Invalid String Length";
return ""
}
if( numCharCnt != 9 )
{
error="Invalid Format String";
return ""
}
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="myFormatters.*">
<!-- Trigger the formatter while populating a string with data. -->
<mx:TextInput text="Your SS number is {SSFormat.format('123456789')}"/>
</mx:Application>
// Constructor
public function ExtendedZipCodeFormatter() {
// Call base class constructor.
super();
// Initialize formatString.
formatString = "#####*####";
}
// Override format().
override public function format(value:Object):String {
// 1. If the formatString is our new pattern,
// then validate and format it.
<!-- Trigger the formatter while populating a string with data. -->
<mx:TextInput width="200"
text="Your zipcode number is {ZipCodeFormat.format('123456789')}"/>
</mx:Application>
144
Contents
Validating data by using custom validators. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
Example: Validating multiple fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
Validator
The remainder of the doValidation() method contains your custom validation logic.
errorMessage A String that contains the error message. You can define your own error messages for your custom
validators.
isError A Boolean value that indicates whether or not the result is an error. Set this property to true.
subField A String that specifies the name of the subfield associated with the ValidationResult object.
In your override of the doValidation() method, you can define an empty Array and populate it with Validation-
Result objects as your validator encounters errors.
// Constructor.
public function AgeValidator() {
// Call base class constructor.
super();
}
return results;
}
}
}
This example first defines a public constructor that calls super() to invoke the constructor of its base class. The base
class can perform the check to ensure that data was entered into a required field, if you set the required property
of the validator to true.
Notice that the second argument of the constructor for the ValidationResult class is null. You use this argument to
specify a subfield, if any, of the object being validated that caused the error. When you are validating a single field,
you can omit this argument. For an example that validates multiple fields, see “Example: Validating multiple fields”
on page 147.
You can use this validator in your Flex application, as the following example shows:
<?xml version="1.0" ?>
<!-- validators/MainAgeValidator.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="myValidators.*">
<MyComp:AgeValidator id="ageV"
required="true"
source="{birthYear}"
property="text" />
<mx:Form >
<mx:FormItem label="Enter birth year: ">
<mx:TextInput id="birthYear"/>
</mx:FormItem>
<mx:FormItem label="Enter birth year: ">
<mx:Button label="Submit"/>
ADOBE FLEX 3 147
Creating and Extending Flex Components
</mx:FormItem>
</mx:Form>
</mx:Application>
The package statement for your custom validator specifies that you should deploy it in a directory called
myValidators. In the previous example, you place it in the subdirectory of the directory that contains your Flex
application. Therefore, the namespace definition in your Flex application is xmlns:MyComp="myValidators.*".
For more information on deployment, see “Compiling Components” on page 40.
<mx:Model id="person">
<name>
<custName>
<first>{firstInput.text}</first>
<middle>{middleInput.text}</middle>
<last>{lastInput.text}</last>
</custName>
</name>
</mx:Model>
<mx:TextInput id="firstInput"/>
<mx:TextInput id="middleInput"/>
<mx:TextInput id="lastInput"/>
<MyComp:NameValidator id="nameVal"
source="{person}" property="custName"
listener="{firstInput}"/>
</mx:Application>
This validator examines three input fields. You specify firstInput as the validation listener. Therefore, when a
validation error occurs, Flex shows a validation error message on the first TextInput control.
You can implement the NameValidator class, as the following example shows:
package myValidators
{
import mx.validators.Validator;
import mx.validators.ValidationResult;
ADOBE FLEX 3 148
Creating and Extending Flex Components
return results;
}
}
}
In this example, because you are using a single validator to validate three subfields of the Object passed to the
validator, you include the optional second argument to the constructor for the ValidationResult class to specify the
subfield that caused the validation error. This inclusion permits Flex to identify the input component that caused the
error, and to highlight that component in the application.
The doValidation() method returns a validation error as soon as it detects the first validation error. You can
modify doValidation() so that it examines all of the input fields before returning an error message, as the
following example shows. This custom valiudator is named NameValidatorAllFields.as:
package myValidators
{
ADOBE FLEX 3 149
Creating and Extending Flex Components
import mx.validators.Validator;
import mx.validators.ValidationResult;
return results;
}
}
}
Notice that you remove the return statement from the body of the if statements so that the method contains only
a single return statemen. This modification allows you to detect three different validation errors at once.
150
Contents
About creating a custom effect . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
About tween effects. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
Writing an effect for a transition. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
Creating a custom data effect . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
Defining a custom effect trigger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168
Effect
Factory classes
EffectInstance
Instance classes
By convention, the name of a factory class is the name of the effect, such as Zoom or Fade.
Instance class The instance class implements the effect logic. When an effect trigger occurs, or when you call the
play() method to invoke an effect, the factory class creates an object of the instance class to perform the effect on
the target. When the effect ends, Flex destroys the instance object. If the effect has multiple target components, the
factory class creates multiple instance objects, one per target.
By convention, the name of an instance class is the name of the effect with the suffix Instance, such as ZoomInstance
or FadeInstance.
• mx.effects.Effect Create a subclass from this class for simple effects that do not require an effect to play over
a period of time. For example, the Pause effect inserts a delay between two consecutive effects. You can also define a
simple sound effect that plays an MP3 file.
• mx.effects.TweenEffect Create a subclass from this class to define an effect that plays over a period of time,
such as an animation. For example, the Resize effect is a subclass of the TweenEffect class that modifies the size of
its target over a specified duration.
constructor (Required) The class constructor. You typically call the super() method to invoke the
superclass constructor to initialize the inherited items from the superclasses.
Your constructor must take at least one optional argument, of type Object. This argu-
ment specifies the target component of the effect.
Effect.initInstance() (Required) Copies properties of the factory class to the instance class. Flex calls this
protected method from the Effect.createInstance() method; you do not have
to call it yourself.
Effect.getAffectedProperties() (Required) Returns an Array of Strings, where each String is the name of a property of
the target object that is changed by this effect. If the effect does not modify any prop-
erties, it should return an empty Array.
Effect.instanceClass (Required) Contains an object of type Class that specifies the name of the instance class
for this effect class.
All subclasses of the Effect class must set this property, typically in the constructor.
Effect.effectEndHandler() (Optional) Called when an effect instance finishes playing. If you override this method,
ensure that you call the super() method.
Effect.effectStartHandler() (Optional) Called when the effect instance starts playing. If you override this method,
ensure that you call the super() method.
Additional methods and properties (Optional) Define any additional methods and properties that the user requires to
configure the effect.
The following table lists the methods and properties that you define in an instance class:
constructor (Required) The class constructor. You typically call the super() method to invoke the
superclass constructor to initialize the inherited items from the superclasses.
EffectInstance.play() (Required) Invokes the effect. You must call super.play() from your override.
EffectInstance.end() (Optional) Interrupts an effect that is currently playing, and jumps immediately to the
end of the effect.
ADOBE FLEX 3 153
Creating and Extending Flex Components
EffectInstance.initEffect() (Optional) Called if the effect was triggered by the EffectManager. You rarely have to
implement this method. For more information, see “Overriding the initEffect() method”
on page 170.
TweenEffectInstance.onTweenUpdate() (Required) Use when you create a subclass from TweenEffectInstance. A callback
method called at regular intervals to implement a tween effect. For more information,
see “Example: Creating a tween effect” on page 157.
TweenEffectInstance.onTweenEnd() (Optional) Use when you create a subclass from TweenEffectInstance. A callback
method called when the tween effect ends. You must call super.onTweenEnd()
from your override. For more information, see “Example: Creating a tween effect” on
page 157.
Additional methods and properties (Optional) Define any additional methods and properties. These typically correspond
to the public properties and methods from the factory class, and any additional prop-
erties and methods that you require to implement the effect.
The package statement in your class specifies that you should deploy it in a directory called myEffects. In this
example, you place it in the subdirectory of the directory that contains your Flex application. Therefore, the
namespace definition in your Flex application is xmlns:MyComp="myEffects.*". For more information on
deployment, see “Compiling Components” on page 40.
To define your instance class, you create a subclass from the mx.effects.EffectInstance class. In the class definition,
you must define a constructor and play() methods, and you can optionally define an end() method to stop the
effect.
package myEffects
{
// myEffects/MySoundInstance.as
import mx.effects.EffectInstance;
import flash.media.SoundChannel;
import flash.media.Sound;
// Define constructor.
public function MySoundInstance(targetObj:Object) {
super(targetObj);
}
</mx:Application>
To make your effects more robust, you often design them to let the user pass parameters to them. The example in
this section modifies the sound effect from the previous section to take a parameter that specifies the MP3 file to
play:
package myEffects
{
// MySoundParam.as
import mx.effects.Effect;
import mx.effects.EffectInstance;
import mx.effects.IEffectInstance;
package myEffects
{
// MySoundParamInstance.as
import mx.effects.EffectInstance;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.net.URLRequest;
// Define constructor.
public function MySoundParamInstance(targetObj:Object) {
super(targetObj);
}
<MyComps:MySoundParam id="mySoundEffect"
soundMP3="http://localhost:8100/flex/assets/sample.mp3"/>
</mx:Application>
ADOBE FLEX 3 157
Creating and Extending Flex Components
This section describes how to create a tween effect. However, Flex supplies the AnimateProperty class that you can
use to create a tween effect for a single property of the target component. For more information, see “Using
Behaviors” on page 519 in Flex Developer’s Guide.
super(targetObj);
instanceClass= RotationInstance;
}
package myEffects
{
// myEffects/RotationInstance.as
import mx.effects.effectClasses.TweenEffectInstance;
import mx.effects.Tween;
In this example, Tween object invokes the onTweenUpdate() callback method on a regular interval, passing it values
between angleFrom and angleTo. At the end of the effect, the Tween object calls the onTweenUpdate() callback
method with a value of angleTo. By invoking the onTweenUpdate() callback method at regular intervals
throughout the duration of the effect, the target component displays a smooth animation as it rotates.
You use your new effect in an MXML application, as the following example shows:
<?xml version="1.0"?>
<!-- effects/MainRotation.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="myEffects.*">
<MyComp:Rotation id="Rotate90"
angleFrom="0" angleTo="360"
duration="1000"/>
<mx:Image source="@Embed(source='../assets/myImage.jpg')"
mouseDownEffect="{Rotate90}"/>
</mx:Application>
In this example, you use the effect to rotate an image when the user clicks it.
Flex uses the following rules to determine the start and end values of effect properties when you use the effect in a
transition:
1 If the effect defines the values of any properties, it uses the properties in the transition, as the following example
shows:
<mx:Transition fromState="*" toState="*">
<mx:Sequence id="t1" targets="{[p1,p2,p3]}">
<mx:Blur duration="100"
blurXFrom="0.0" blurXTo="10.0" blurYFrom="0.0" blurYTo="10.0"/>
<mx:Parallel>
<mx:Move duration="400"/>
<mx:Resize duration="400"/>
</mx:Parallel>
<mx:Blur duration="100"
blurXFrom="10.0" blurXTo="0.0" blurYFrom="10.0" blurYTo="0.0"/>
</mx:Sequence>
</mx:Transition>
ADOBE FLEX 3 160
Creating and Extending Flex Components
In this example, the two Blur filters define the properties of the effect.
2 If the effect does not define the start values of the effect, the effect determines the values from the EffectIn-
stance.propertyChanges property passed to the effect instance. Flex sets the propertyChanges property by
using information from the current settings of the component, as defined by the current view state. For more infor-
mation on the propertyChanges property, see “How Flex initializes the propertyChanges property” on page 160.
In the example in step 1, notice that the Move and Resize effects do not define start values. Therefore, Flex deter-
mines the start values from the current size and position of the effect targets in the current view state, and passes
that information to each effect instance by using the propertyChanges property.
3 If the effect does not define the end values of the effect, the effect determines the values from the
Effectinstance.propertyChanges property passed to the effect instance. Flex sets the propertyChanges
property by using information about the component, as defined by the destination view state. For more information
on the propertyChanges property, see “How Flex initializes the propertyChanges property” on page 160.
In the example in rule 1, Flex determines the end values of the Move and Resize effects from the size and position
of the effect targets in the destination view state. In some cases, the destination view state defines those values.
If the destination view state does not define the values, Flex determines them from the setting of the base view
state, and passes that information to each effect instance by using the propertyChanges property.
4 If there are no explicit values, and Flex cannot determine values from the current or destination view states, the
effect uses its default property values.
Property Description
target A target component of the effect. The end and start properties of the PropertyChanges class define how the target
component is modified by the change to the view state.
start An object that contains the starting properties of the target component, as defined by the current view state. For
example, for a target component that is moved and resized by a change to the view state, the start property contains
the starting position and size of the component, as the following example shows:
end An object that contains the ending properties of the target component, as defined by the destination view state. For
example, for a target component that is moved and resized by a change to the view state, the end property contains
the ending position and size of the component, as the following example shows:
In the body of the Effectinstance.play() method, you can examine the information in the propertyChanges
property to configure the effect.
}
}
}
In the RotationTransInstance.as class, you modify the play() method to calculate the default values for the
angleFrom and angleTo properties. This method performs the following actions:
1 Determines whether the user set values for the angleFrom and angleTo properties.
2 If not, determines whether the Effectinstance.propertyChanges property was initialized with start and end
values. If so, the method uses those values to configure the effect.
3 If not, sets the angleFrom and angleTo properties to the default values of 0 for the angleFrom property, and
360 for the angleTo property.
The following example shows the RotationTransInstance.as class:
package myEffects
{
// myEffects/RotationTransInstance.as
import mx.effects.effectClasses.TweenEffectInstance;
import mx.effects.Tween;
<!-- Define the two view states, in addition to the base state.-->
<mx:states>
<mx:State name="One">
<mx:SetProperty target="{p1}" name="x" value="110"/>
<mx:SetProperty target="{p1}" name="y" value="0"/>
<mx:SetProperty target="{p1}" name="width" value="200"/>
<mx:SetProperty target="{p1}" name="height" value="210"/>
<mx:SetProperty target="{p2}" name="x" value="0"/>
<mx:SetProperty target="{p2}" name="y" value="0"/>
<mx:SetProperty target="{p2}" name="width" value="100"/>
<mx:SetProperty target="{p2}" name="height" value="100"/>
<mx:SetProperty target="{p3}" name="x" value="0"/>
<mx:SetProperty target="{p3}" name="y" value="110"/>
<mx:SetProperty target="{p3}" name="width" value="100"/>
<mx:SetProperty target="{p3}" name="height" value="100"/>
</mx:State>
<mx:State name="Two">
<mx:SetProperty target="{p2}" name="x" value="110"/>
<mx:SetProperty target="{p2}" name="y" value="0"/>
<mx:SetProperty target="{p2}" name="width" value="200"/>
<mx:SetProperty target="{p2}" name="height" value="210"/>
<mx:SetProperty target="{p3}" name="x" value="0"/>
<mx:SetProperty target="{p3}" name="y" value="110"/>
<mx:SetProperty target="{p3}" name="width" value="100"/>
<mx:SetProperty target="{p3}" name="height" value="100"/>
</mx:State>
</mx:states>
<!-- Define the single transition for all view state changes.-->
<mx:transitions>
<mx:Transition fromState="*" toState="*">
<mx:Sequence id="t1" targets="{[p1,p2,p3]}">
<mx:Parallel>
<mx:Move duration="400"/>
<mx:Resize duration="400"/>
</mx:Parallel>
<MyComp:RotationTrans filter="move"/>
</mx:Sequence>
</mx:Transition>
</mx:transitions>
ADOBE FLEX 3 164
Creating and Extending Flex Components
<!-- Define the Canvas container holdig the three Panel containers.-->
<mx:Canvas id="pm" width="100%" height="100%" >
<mx:Panel id="p1" title="One"
x="0" y="0" width="100" height="100"
click="currentState='One'" >
<mx:Label fontSize="24" text="One"/>
</mx:Panel>
<mx:Panel id="p2" title="Two"
x="0" y="110" width="100" height="100"
click="currentState='Two'" >
<mx:Label fontSize="24" text="Two"/>
</mx:Panel>
<mx:Panel id="p3" title="Three"
x="110" y="0" width="200" height="210"
click="currentState=''" >
<mx:Label fontSize="24" text="Three"/>
</mx:Panel>
</mx:Canvas>
</mx:Application>
AddItemAction Defines an effect that determines when the item renderer appears in the control for an item being added to
a list-based control, or for an item that replaces an existing item in the control.
RemoveItemAction Defines an effect that determines when the item renderer disappears from the control for the item renderer
of an item being removed from a list-based control, or for an item that is replaced by a new item added to the
control.
UnconstrainItemAction Defines an effect that to temporarily stop item renderers from being positioned by the layout algorithm of
the parent control. Use this effect to allow item renderers in a TileList control to move freely rather than being
constrained to lay in the normal grid that is defined by the control. You typically add this effect when your
custom data effect moves item renderers.
You can use the Effect.filter property to filter possible effect targets, which lets you play an effect only on a
subset of the item renderers in the list-based control. The following table lists the values of the Effect.filter
property that you use with data effects:
addItem Play the effect on the item renderer for any list items added to a List or TileList control.
removeItem Play the effect on the item renderer for any list items removed from a List or TileList control.
replacedItem Play the effect on the item renderer for any list items replaced in a List or TileList control by a new item.
replacementItem Play the effect on the item renderer for any list items added to a List or TileList control that replaces an existing
item.
ADOBE FLEX 3 165
Creating and Extending Flex Components
For detailed information and examples of action effects and effect filters, see “Using action effects in a transition” on
page 840 and “Filtering effects” on page 843.
<mx:Script>
<![CDATA[
import mx.effects.easing.Elastic;
import mx.collections.ArrayCollection;
[Bindable]
private var myDP:ArrayCollection = new ArrayCollection(
['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q']);
<mx:Blur
blurYTo="12" blurXTo="12"
duration="300"
perElementOffset="150"
filter="removeItem"/>
<mx:UnconstrainItemAction/>
<mx:Parallel>
<mx:Move
duration="750"
easingFunction="{Elastic.easeOut}"
perElementOffset="20"/>
<mx:RemoveItemAction
startDelay="400"
filter="removeItem"/>
<mx:AddItemAction
startDelay="400"
filter="addItem"/>
<mx:Blur
startDelay="410"
blurXFrom="18" blurYFrom="18" blurXTo="0" blurYTo="0"
duration="300"
filter="addItem"/>
</mx:Parallel>
</mx:Sequence>
<mx:Button
label="Delete selected item(s)"
click="deleteItem();"/>
<mx:Button
label="Add item"
click="addItem();"/>
</mx:Application>
This example uses the Effect.filter property to filter possible effect targets. Because you set the filter property
of the first Blur effect to removeItem, Flex only applies the effect to items added to the list control. Because the Move
effect omits the filter property, Flex applies the effect to all items in the control.
You can create a custom filter by passing an instance of the EffectTargetFiler class to the Effect.customFilter
property. For example, the Effect.filter property only lets you specify a single value, such as addItem or
removeItem. But, you can use the EffectTargetFiler.requiredSemantics property to specify a collection of
properties and associated values which must be associated with a target for the effect to be played. For more infor-
mation, see “Filtering effects” on page 843 in Flex Developer’s Guide.
ADOBE FLEX 3 167
Creating and Extending Flex Components
<mx:Script>
<![CDATA[
import mx.effects.easing.Elastic;
]]>
</mx:Script>
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import myComponents.MyDataEffect;
[Bindable]
private var myDP:ArrayCollection = new ArrayCollection(
['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q']);
<mx:Button
label="Delete selected item(s)"
click="deleteItem();"/>
<mx:Button
label="Add item"
click="addItem();"/>
</mx:Application>
Suppose that you want to apply an effect that sets the brightness level of a component when a user action occurs. The
following example shows a custom Button control that uses a new property, bright, and dispatches two new events,
darken and brighten, based on changes to the bright property. The control also defines two new effect triggers,
darkenEffect and brightenEffect, which are paired with the darken event and the brighten event.
<?xml version="1.0"?>
<!-- effects\myComponents\MyButton.mxml -->
<mx:Button xmlns:mx="http://www.adobe.com/2006/mxml" >
<mx:Metadata>
<!-- Define the metadata for the events and effect triggers. -->
[Event(name="darken", type="flash.events.Event")]
[Event(name="brighten", type="flash.events.Event")]
[Effect(name="darkenEffect", event="darken")]
[Effect(name="brightenEffect", event="brighten")]
</mx:Metadata>
<mx:Script>
<![CDATA[
import flash.events.Event;
if (_bright)
dispatchEvent(new Event("brighten"));
else
dispatchEvent(new Event("darken"));
}
</mx:Button>
When you declare an event in the form [Event(name="eventName", type="package.eventType")], you can
also create a corresponding effect, in the form [Effect(name="eventnameEffect", event="eventname")]. As in
the previous example, in the <mx:Metadata> tag, you insert the metadata statements that define the two new events,
darken and brighten, and the new effect triggers, darkenEffect and brightenEffect, to the Flex compiler.
For more information on using metadata, see “Using Metadata Tags in Custom Components” on page 27.
The application in the following example uses the MyButton control. The darkenEffect and brightenEffect
properties are set to the FadeOut and FadeIn effects, respectively. The click event of a second Button control toggles
the MyButton control’s bright property and executes the corresponding effect (FadeOut or FadeIn).
<?xml version="1.0"?>
<!-- effects/MainMyButton.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="myComponents.*" >
<!-- Define two fade effects for darkening and brightening target. -->
ADOBE FLEX 3 170
Creating and Extending Flex Components
</mx:Application>
where event is the Event object dispatched by the event that triggered the effect.
For example, a user might create an instance of an effect, but not provide all of the configuration information that is
required to play the effect. Although you might be able to assign default values to all properties within the definition
of the effect class, in some cases you might have to determine the default values at run time.
In this method, you can examine the Event object and the effect target to calculate values at run time. For more infor-
mation on how to create a custom event and an effect trigger, see “Defining a custom effect trigger” on page 168. As
part of that example, you can add properties to the Event object passed to the dispatchEvent() method. You can
then access that Event object, and its additional properties, from the initEffect() method.
By overriding the initEffect() method, you can also access the target property of the Event object to reference
the target component of the effect. For example, if you must determine the current x and y coordinates of the
component, or its current height and width, you can access them from your override of the initEffect() method.
171
Index
A using metadata statements 28 custom 73
accessibility, custom CSS defining in ActionScript
components 114 inheritance 124 components 93
ActionScript setting styles 125 dispatching custom events 22
classpath 41 custom components Event metadata keyword 29, 34, 38
coding practices 13 best practices 115 Event metadata tag 23
custom components 10 compound 115 from composite components 75
defining components 80 metadata 28 handling 72
distributing components as 44 types 10 NonCommittingChangeEvent
Application object, accessing 68 metadata keyword 37
versioning 115
extending classes 6
custom effect trigger 168
B extending graphical components 115
custom effects
behaviors creating 150
in applications 150 F
factory and instance classes 151
defining custom effects 154 faceless components, definition 10
custom events, dispatching 22, 94
Bindable metadata keyword 29 factory class 151
custom properties, data binding 87
formatters
custom, formatting 138
C error handling 140
class hierarchy 6 extending 142
D
class statement 15 formatting, data
data binding
classes custom 138
custom properties 87
extending classes and subclasses 6 ZIP codes 140
in custom properties 66
hierarchy for components 6, 80 data validation 144
classpath, ActionScript 41 G
data, custom formatters 138
commitProperties() method 105, 106 getters 17, 65
default property 86
compiling DefaultProperty metadata
about 40 keyword 32 I
compc 40 deferred creation 133 IconFile metadata keyword 29
mxmlc 40 deploying components 11 IDeferredInstance interface 134
web-tier compiler 41 dispatchEvent() method 95 images, Embed metadata keyword 29
component instantiation life import statement 14
cycle 100 Inspectable metadata keyword 30
E
components Effect metadata keyword 29 instance class 151
class hierarchy 6, 80 effects InstanceType metadata keyword 37
compound 115 custom 150 interfaces
getters and setters 17, 65 custom effect trigger 168 about 76, 102
composite MXML components 51 defining custom 154 IMXMLObject interface 77
compound components 115 for transitions 159
constructor tween effects 157 K
about 15 Embed metadata keyword 29 keywords, metadata 29
implementing 104 Event class, creating a subclass 22
createChildren() method 104 Event metadata keyword 29, 34, 38 L
creating components events layoutChrome() method 111
adding events 95 about 20 life cycle, component
extending a class 6 instantiation 100
adding 95
INDEX 172
M S
measure() method 108 scope
metadata keywords about 19
available 29 custom components 53
Bindable 29 screen readers, accessibility in
custom components 28 custom components 114
Embed 29 setters, defining for custom
components 17, 65
Event 34, 38
skins, style property 130
NonCommittingChangeEvent 37
startup time, RSLs 11, 43
Style 38, 39, 127
static constants 25
syntax 28
Style metadata keyword 30, 38, 39,
tags 29 127
using 28 styles
metadata tags about 124
about 27 custom components 54, 96
Event 23 setting 125
methods setting defaults 129
defining 17 Style metadata keyword 30, 38, 39,
overrides 90 127
MXML super keyword 18
ActionScript classes and 6 SWC files, distributing components
custom components 8 as 43
custom properties and methods 62 syntax, for metadata statements 28
multiple files 49
MXML components T
about 49 tags
creating 49 for metadata 29
reusable 61 See also specific tag names
template components
N about 131
NonCommittingChangeEvent data types 133
metadata keyword 30, 37 transitions 159
troubleshooting 122
P tween effects 157
package statement 13 type selector 57
performance, RSLs 11, 43
postal codes, formatting 140 U
properties updateDisplayList() method 111
as getters and setters 17
as variables 16 V
commitProperties() method 106 validation, multiple fields
getter and setters 85 example 147
getters and setters 65 validators 144
inspectable 66 VBox layout, overriding 112
MXML 64 versioning 115
visual components 98
R
runtime shared libraries (RSLs),
definition 11, 43