You define custom ActionScript components to extend the Flex component library. For example, you can create a customized Button, Tree, or DataGrid component as an ActionScript component.
For information on creating advanced components in ActionScript, see Create advanced Spark visual components in ActionScript and Create advanced MX visual components in ActionScript.
You create reusable components by using ActionScript, and reference these components in your Flex applications as MXML tags. Components created in ActionScript can contain graphical elements, define custom business logic, or extend existing Flex components.
Flex components are implemented as a class hierarchy in ActionScript. Each component in your application is an instance of an ActionScript class. 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. For a complete description of the class hierarchy, see the ActionScript 3.0 Reference for Apache Flex.
The class you choose to use as the superclass of your custom component depends on what you are trying to accomplish. For example, you might require a custom button control. You could create a subclass of the UIComponent class, and 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.
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 Create advanced MX visual components in ActionScript.
When you define a simple component, you do not create a component yourself, but instead modify the behavior of an existing component. In this section, you create a customized TextArea control by extending the spark.components.TextArea component. This component adds an event listener for the keyDown event to the TextArea control. The KeyDown event deletes all the text in the control when a user presses the Control+Alt+Z key combination.
package myComponents
{
// createcomps_as/myComponents/DeleteTextArea.as
import spark.components.TextArea;
import flash.events.KeyboardEvent;
public class DeleteTextArea extends TextArea {
// Constructor
public function DeleteTextArea() {
// Call super().
super();
// Add event listener for keyDown event.
addEventListener("keyDown", myKeyDown);
}
// Define private keyDown event handler.
private function myKeyDown(eventObj:KeyboardEvent):void {
// Check to see if Ctrl+Alt+Z pressed. Keycode is 90.
if (eventObj.ctrlKey && eventObj.keyCode == 90)
text = "";
}
}
}
The filename for this component is DeleteTextArea.as, and its location is the myComponents subdirectory of the application, as specified by the package statement. For more information on using the package statement and specifying the directory location of your components, see Custom ActionScript components.
You can now use your new TextArea control in an application, as the following example shows:
<?xml version="1.0"?>
<!-- createcomps_as/MainDeleteTextArea.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:MyComp="myComponents.*">
<MyComp:DeleteTextArea/>
</s:Application>
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"?>
<!-- createcomps_as/MainDeleteTextAreaProps.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:MyComp="myComponents.*">
<MyComp:DeleteTextArea
maxChars="50"
text="My Message"/>
</s: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 spark.components.TextArea;
import flash.events.KeyboardEvent;
public class TextArea extends TextArea {
...
}
}
You can now use your custom TextArea control, and the standard TextArea control, in an application. To differentiate between the two controls, you use the namespace prefix, as the following example shows:
<?xml version="1.0"?> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:MyComp="myComponents.*" > <MyComp:TextArea/> <s:TextArea/> </s:Application>
To make your custom components reusable, you design them so that users can pass information to them. You do this by adding public properties and methods to your components, and by making the components accessible in MXML.
You can use one of the following methods to add public properties to your ActionScript components:
Define public variables
Define public getter and setter methods
All public properties defined in your component are accessible in MXML by using MXML tag properties. For example, you might allow the user to pass a value to your component, as the following example shows:
<MyComp:MyCustomComponent prop1="3"/>
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 {
// Define an uninitialized variable.
public var prop1:Number;
// Define and initialize a variable.
public var prop2:Number=5;
...
}
You can also use public getter and setter methods to define a property, as the following example shows:
public class MyCustomComponent extends TextArea {
private var _prop1:Number;
public function get prop1():Number {
// Method body.
// Typically the last line returns the value of the private variable.
return _prop1;
}
public function set prop1(value:Number):void {
// Typically sets the private variable to the argument.
_prop1=value;
// Define any other logic, such as dispatching an event.
}
}
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.
In the following example, you use the Control+Alt+I key combination to extend the TextArea control to let the user increase the font size by one point, or use the Control+Alt+M key combination to decrease the font size by one point:
package myComponents
{
// createcomps_as/myComponents/TextAreaFontControl.as
import spark.components.TextArea;
import flash.events.KeyboardEvent;
import flash.events.Event;
public class TextAreaFontControl extends TextArea
{
// Constructor
public function TextAreaFontControl() {
super();
// Add event listeners.
addEventListener("keyDown", myKeyDown);
addEventListener("creationComplete", myCreationComplete);
}
// Define private var for current font size.
private var currentFontSize:Number;
// Define a public property for the minimum font size.
public var minFontSize:Number = 5;
// Define a public property for the maximum font size.
public var maxFontSize:Number = 15;
// Initialization event handler for getting default font size.
private function myCreationComplete(eventObj:Event):void {
// Get current font size
currentFontSize = getStyle('fontSize');
}
// keyDown event handler.
private function myKeyDown(eventObj:KeyboardEvent):void {
// Was Ctrl key pressed?
if (eventObj.ctrlKey)
{
switch (eventObj.keyCode) {
// Was Ctrl+Alt+I pressed?
case 73 :
if (currentFontSize < maxFontSize) {
currentFontSize = currentFontSize + 1;
setStyle('fontSize', currentFontSize);
}
break;
// Was Ctrl+Alt+ pressed?
case 77 :
if (currentFontSize > minFontSize) {
currentFontSize = currentFontSize - 1;
setStyle('fontSize', currentFontSize);
}
break;
default :
break;
}
}
}
}
}
Notice that the call to the getStyle() method is in the event listener for the creationComplete event. You must wait until component creation is complete before calling getStyle() to ensure that Flex has set all inherited styles. However, you can call setStyle() in the component constructor to set styles.
This example uses variables to define public properties to control the maximum font size, maxFontSize, and minimum font size, minFontSize, of the control. Users can set these properties in MXML, as the following example shows:
<?xml version="1.0"?>
<!-- createcomps_as/MainTextAreaFontControl.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:MyComp="myComponents.*">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<MyComp:TextAreaFontControl id="myTAFS"
minFontSize="8"
maxFontSize="50"/>
<s:Button
label="Get Font Size"
click="myTA.text=String(myTAFS.getStyle('fontSize'));"/>
<s:TextArea id="myTA"/>
</s:Application>
There are no restrictions on using public variables to define public properties, However, it's best to use getter and setter methods so that you can control user interaction with your component, as described in Defining properties as getters and setters.
The following example code defines a component named TextAreaFontControlGetSet that replaces the public property definition for the maxFontSize property shown in Defining public properties as variables:
package myComponents
{
// createcomps_as/myComponents/TextAreaFontControlGetSet.as
import spark.components.TextArea;
import flash.events.KeyboardEvent;
import flash.events.Event;
public class TextAreaFontControlGetSet extends TextArea
{
public function TextAreaFontControlGetSet()
{
super();
addEventListener("keyDown", myKeyDown);
addEventListener("creationComplete", myCreationComplete);
}
private var currentFontSize:Number;
public var minFontSize:Number = 5;
// Define private variable for maxFontSize.
private var _maxFontSize:Number = 15;
// Define public getter method.
public function get maxFontSize():Number {
return _maxFontSize;
}
// Define public setter method.
public function set maxFontSize(value:Number):void {
if (value <= 30) {
_maxFontSize = value;
} else _maxFontSize = 30;
}
private function myCreationComplete(eventObj:Event):void {
// Get current font size
currentFontSize = getStyle('fontSize');
}
// keyDown event handler.
private function myKeyDown(eventObj:KeyboardEvent):void {
// Was Ctrl key pressed?
if (eventObj.ctrlKey)
{
switch (eventObj.keyCode) {
// Was Ctrl+Alt+I pressed?
case 73 :
if (currentFontSize < maxFontSize) {
currentFontSize = currentFontSize + 1;
setStyle('fontSize', currentFontSize);
}
break;
// Was Ctrl+Alt+M pressed?
case 77 :
if (currentFontSize > minFontSize) {
currentFontSize = currentFontSize - 1;
setStyle('fontSize', currentFontSize);
}
break;
default :
break;
}
}
}
}
}
In this example, the setter method checks that the specified font size is less than the predefined limit of 30 pixels. If the font size is greater than the limit, it sets it to the limit.
You can define a default property for your ActionScript components by using the [DefaultProperty] metadata tag. You can then use the default property in MXML as the child tag of the component tag without specifying the property name. For more information on using the default property, including an example, see Defining public properties as variables.
You can use the [DefaultProperty] metadata tag in your ActionScript component to define a single default property, as the following example shows:
package myComponents
{
// createcomps_as/myComponents/TextAreaDefaultProp.as
import spark.components.TextArea;
// Define the default property.
[DefaultProperty("defaultText")]
public class TextAreaDefaultProp extends TextArea {
public function TextAreaDefaultProp()
{
super();
}
// Define a setter method to set the text property
// to the value of the default property.
public function set defaultText(value:String):void {
if (value!=null)
text=value;
}
public function get defaultText():String {
return text;
}
}
}
In this example, you add a new property to the TextArea control, called defaultText, and specify it as the default property of the control. The setter method for defaultText just sets the value of the text property of the control. You can then use the default property in MXML, as the following example shows:
<?xml version="1.0"?>
<!-- createcomps_as/MainTextAreaDefaultProp.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:MyComp="myComponents.*">
<MyComp:TextAreaDefaultProp>Hello</MyComp:TextAreaDefaultProp>
</s: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:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:MyComp="myComponents.*">
<MyComp:defaultText>Hello</MyComp:defaultText>
</MyComp:TextAreaDefaultProp>
Data binding defines a syntax for automatically copying the value of a property of one object, the source property, to a property of another object, the destination property, at run time. Data binding is usually triggered when the value of the source property changes.
The following example shows a Text control that gets its data from a HSlider control's value property. The property name inside the curly braces ({ }) specifies a binding expression that copies the value of the source property, mySlider.value, into the destination property, the Text control's text property.
<mx:HSlider id="mySlider"/>
<mx:Text text="{mySlider.value}"/>
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.
Properties in your custom components can take advantage of data binding. Any property defined as a variable or defined by using a setter and getter method can automatically be used as the destination of a binding expression.
For example, in the section Defining public properties in ActionScript, you created a class with the public property maxFontSize. You can use the maxFontSize property as the destination of a binding expression, as the following example shows:
<?xml version="1.0"?>
<!-- createcomps_as/MainTextAreaFontControlBindingDest.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:MyComp="myComponents.*" >
<s:layout>
<s:VerticalLayout/>
</s:layout>
<MyComp:TextAreaFontControl id="myTA"
maxFontSize="{Number(myTI.text)}"/>
<s:Label text="Enter max font size."/>
<s:TextInput id="myTI" text="25"/>
</s:Application>
In this example, any value that the user enters into the TextInput control is automatically copied to the maxFontSize property.
When a property is the source of a data binding expression, Flex automatically copies the value of the source property to any destination property when the source property changes. However, in order to signal to Flex to perform the copy, you must register the property with Flex and the source property must dispatch an event.
To register a property as a source for data bindings, you use the [Bindable] metadata tag. You can use this tag in three places:
Before a class definition, in order to make all public properties defined as variables usable as the source of a binding expression. You can also do this by using setter and getter methods, in which case you use the [Bindable] tag before the getter method.
Before a property that a variable defines, in order to make that specific property support binding
Before a getter method for a property implemented by using setter and getter methods
For more information on the [Bindable] metadata tag, see Metadata tags in custom components.
The following example modifies the component in the section Defining public properties in ActionScript 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;
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 operation, 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
{
// createcomps_as/myComponents/TextAreaFontControlBinding.as
import spark.components.TextArea;
import flash.events.KeyboardEvent;
import flash.events.Event;
public class TextAreaFontControlBinding extends TextArea
{
public function TextAreaFontControlBinding()
{
super();
addEventListener("keyDown", myKeyDown);
addEventListener("creationComplete", myCreationComplete);
}
private var currentFontSize:Number;
public var minFontSize:Number = 5;
// Define private variable for maxFontSize.
public var _maxFontSize:Number = 15;
// Define public getter method, mark the property
// as usable for the source of data binding,
// and specify the name of the binding event.
[Bindable("maxFontSizeChanged")]
public function get maxFontSize():Number {
return _maxFontSize;
}
// Define public setter method.
public function set maxFontSize(value:Number):void {
if (value <= 30) {
_maxFontSize = value;
} else _maxFontSize = 30;
// Dispatch the event to trigger data binding.
dispatchEvent(new Event("maxFontSizeChanged"));
}
private function myCreationComplete(eventObj:Event):void {
// Get current font size
currentFontSize = getStyle('fontSize');
}
// keyDown event handler.
private function myKeyDown(eventObj:KeyboardEvent):void {
// Was Ctrl key pressed?
if (eventObj.ctrlKey)
{
switch (eventObj.keyCode) {
// Was Ctrl+Alt+I pressed?
case 73 :
if (currentFontSize < maxFontSize) {
currentFontSize = currentFontSize + 1;
setStyle('fontSize', currentFontSize);
}
break;
// Was Ctrl+Alt+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"?>
<!-- createcomps_as/MainTextAreaFontControlBindingSource.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:MyComp="myComponents.*">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<MyComp:TextAreaFontControlBinding id="myTA"
maxFontSize="{Number(myTI.text)}"/>
<s:Label text="Enter max font size."/>
<s:TextInput id="myTI" text="15"/>
<s:Label text="Current max font size."/>
<s:TextArea text="{String(myTA.maxFontSize)}"/>
</s:Application>
You can override a method of a base class in your ActionScript component. To override the method, you add a method with the same signature to your class, and prefix it with the override keyword. The following example overrides the HGroup.addElement() method to open an Alert box when a new item is added to it:
package myComponents
{
// createcomps_as/myComponents/HGroupWithAlert.as
import mx.controls.Alert;
import spark.components.HGroup;
import mx.core.IVisualElement;
public class HGroupWithAlert extends HGroup
{
// Define the constructor.
public function HGroupWithAlert() {
super();
}
// Define the override.
override public function addElement(child:IVisualElement):IVisualElement {
// Call super.addChild().
super.addElement(child);
// Open the Alert box.
Alert.show("Item added successfully");
return child;
}
}
}
Notice that the method implementation calls the super.addElement() method. The call to super.addElement() causes Flex to invoke the superclass's addElement() method to perform the operation. Your new functionality to open the Alert box occurs after the super.addElement() 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"?>
<!-- createcomps_as/MainHBoxWithAlert.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:MyComp="myComponents.*">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<fx:Script>
<![CDATA[
import spark.components.Button;
public function addButton():void {
var myButton:Button = new Button();
myButton.label = "New Button";
myHGroup.addElement(myButton);
}
]]>
</fx:Script>
<MyComp:HGroupWithAlert id="myHGroup"/>
<s:Button label="Add Button"
click="addButton();"/>
</s:Application>
In an MXML component, you can initialize the value of any inherited public, writable property by defining a child tag of the MXML component with an id property that matches the name of the inherited property. For example, you define a custom Panel component based on the Flex Panel container, named MyPanel.as, as the following example shows:
package myComponents
{
// createcomps_as/myComponents/MyPanel.as
import spark.components.Panel;
import spark.components.TextInput;
public class MyPanel extends Panel {
// Define public variables for two child components.
public var myInput:TextInput;
public var myOutput:TextInput;
public function MyPanel() {
super();
}
// Copy the text from one child component to another.
public function xfer():void {
myOutput.text = myInput.text;
}
}
}
In this example, the MyPanel component defines two variables corresponding to TextInput controls. You then create a custom MXML component, named MyPanelComponent.mxml, based on MyPanel.as, as the following example shows:
<?xml version="1.0"?>
<!-- createcomps_as/myComponents/MyPanelComponent.mxml -->
<MyComps:MyPanel xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:MyComps="myComponents.*">
<MyComps:layout>
<s:VerticalLayout/>
</MyComps:layout>
<s:TextInput id="myInput"/>
<s: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"?>
<!-- createcomps_as/MainCodeBehindExample.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:MyComps="myComponents.*">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<MyComps:MyPanelComponent id="myP"/>
<s:Button label="Copy" click="myP.xfer();"/>
</s: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:
The inherited property must be public.
If you try to initialize a nonpublic inherited property, the Flex compiler issues an error.
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.
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.
Flex components dispatch their own events and listen to other events. An object that wants to know about another object's events registers as a listener with that object. When an event occurs, the object dispatches the event to all registered listeners.
The core class of the Flex architecture, mx.core.UIComponent, defines core events, such as updateComplete, resize, move, creationComplete, and others that are fundamental to all components. Subclasses of these classes inherit and dispatch these events.
<?xml version="1.0" encoding="utf-8"?>
<!-- createcomps_as/MainMyButtonAS.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:MyComp="myComponents.*">
<fx:Script>
<![CDATA[
import flash.events.Event;
private function handleClick(eventObj:Event):void {
// Define event listener.
}
private function handleCreationComplete(eventObj:Event):void {
// Define event listener.
}
]]>
</fx:Script>
<MyComp:MyButton
click="handleClick(event);"
creationComplete="handleCreationComplete(event);"/>
</s: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 showed how to define a custom event so that properties of your component can work with the Flex data binding mechanism.
The previous example showed a custom component, MyButton, dispatching two events. In that example, you defined the event listeners in the main application file.
Your custom component can also define event listeners within the component itself to handle the events internally. For example, Defining public properties as variables defined event listeners for the keyDown and creationComplete events within the body of the component. This allows the component to handle those events internally.
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 Create advanced MX visual components in ActionScript.
Your ActionScript component can define custom events and use the predefined events. You use custom events to support data binding, to respond to user interactions, or to trigger actions by your component. For an example that uses events to support data binding, see Using data binding with custom properties.
For each custom event dispatched by your component, you must do the following:
Create an Event object describing the event.
(Optional) Use the [Event] metadata tag to make the event public so that other components can listen for it.
Dispatch the event by using the dispatchEvent() method.
To add information to the event object, you define a subclass of the flash.events.Event class to represent the event object. For more information on creating custom event classes, see Custom events.
You might define some custom events that are used internally by your component, and are not intended to be recognized by the other components. For example, the following component defines a custom event, dispatches it, and handles it all within the component:
package myComponents
{
// createcomps_as/myComponents/ModalTextEvent.as
import spark.components.TextArea;
import flash.events.Event;
[Event(name="enableChanged", type="flash.events.Event")]
public class ModalTextEvent extends TextArea {
public function ModalTextEvent() {
super();
// Register event listener.
addEventListener("enableChanged", enableChangedListener);
}
public function enableInput(value:Boolean):void {
// Method body.
// Dispatch event.
dispatchEvent(new Event("enableChanged"));
}
private function enableChangedListener(eventObj:Event):void {
// Handle event.
}
}
}
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, as the following example shows:
[Event(name="enableChanged", type="flash.events.Event")]
public class ModalTextEvent 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 -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:MyComps="myComponents.*">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<fx:Script>
<![CDATA[
import flash.events.Event;
private function handleEnableChanged(event:Event):void {
myTA.text="Got Event";
}
]]>
</fx:Script>
<MyComps:ModalTextEvent id="myMT"
enableChanged="handleEnableChanged(event);"/>
<s:Button click="myMT.enableInput(true);"/>
<s:TextArea id="myTA"/>
</s:Application>
Style properties define the look of a component, from the size of the fonts used to the color of the background. Your custom ActionScript components inherit all of the styles of the base class, so you can set them in the same way as for that base class.
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 fontWeight styles of the BlueButton control:
package myComponents
{
// createcomps_as/myComponents/BlueButton.as
import spark.components.Button;
public class BlueButton extends Button
{
public function BlueButton() {
super();
// Set the label text to blue.
setStyle("color", 0x0000FF);
// Set the borderColor to blue.
setStyle("fontWeight", "bold");
}
}
}
The following MXML file uses the BlueButton control with the default color and fontWeight styles set in your component's class file:
<?xml version="1.0"?>
<!-- createcomps_as/ASMainBlueButton.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:MyComps="myComponents.*">
<MyComps:BlueButton label="Submit"/>
</s:Application>
Setting the styles in a 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 -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:MyComps="myComponents.*">
<MyComps:BlueButton label="Submit" color="0xFF0000"/>
</s: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 the parent control's class information.
You can also define new style properties for your components. For more information, see Custom style properties.
If you package your component in a SWC file, 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.
Navigation
Adobe and Adobe Flash Platform are either registered trademarks or trademarks of Adobe Systems Incorporated in the United States and/or other countries and are used by permission from Adobe. No other license to the Adobe trademarks are granted.