by Adobe

adobe_logo_bio

Created

22 March 2010

Requirements
User level
All
MXML and ActionScript languages have different own strengths and weaknesses for creating components:
 
  • When you create composite controls declaratively, MXML makes it easier to create and lay out child controls.
  • When you modify the behavior of components, that is, override their methods, you typically use ActionScript.
Most of the time, you use a combination of MXML and ActionScript when you build Flex components and applications. Flex provides several ways of using MXML and ActionScript together, including the following:
 
  • Placing ActionScript statements directly within MXML tags. This is used when defining inline event handlers.
  • Placing ActionScript statements within the <fx:Script> tag.
  • Including external ActionScript files by using the source property of the <fx:Script> tag.
  • Use MXML code to lay out your component and placing ActionScript code in a class definition. This is known as code behind.
To link the ActionScript and MXML files together with code behind, you make the ActionScript class the root tag of your MXML component; that is, your MXML component extends the ActionScript class. For example, to create a custom AddressForm component that displays a composite address entry form, you do the following:
 
  1. Create an ActionScript class called AddressFormClass. You can make this class extend a base Flex class. In this case, you use the layout capabilities of the Form container and make AddressFormClass extend the mx.containers.Form class.
  2. Create an MXML component called AddressForm and make its root tag AddressFormClass.
  3. Use MXML to layout the contents of the AddressForm component.
  4. Use ActionScript to create the logic for the AddressForm component.
Tip: You must declare child controls as public properties in your ActionScript class.
 
The following example contains the custom AddressForm component described above. The main application file also makes use of code behind and the example also features the CountryComboBoxSimpleMXML and PaddedPanel components that you created in the other tutorials.
 
Note: Consider this as an introduction to best practices architecture when building Flex applications. For more information, refer to the Arp framework—an open source pattern-based framework for creating Flash and Flex applications that uses code behind.
 
 
Example
components/AddressFormClass.as
 
// components/AddressFormClass.as package components { import components.CountryComboBoxSimpleMXML; import flash.events.MouseEvent; import mx.containers.Form; import mx.controls.Button; import mx.controls.TextInput; import mx.events.FlexEvent; public class AddressFormClass extends Form { // Components in the MXML must be // declared public. This is a limitation in // the current version of Flex and may change // in the future. public var submitButton:Button = new Button(); public var nameInput:TextInput = new TextInput(); public var street:TextInput = new TextInput(); public var city:TextInput = new TextInput(); public var state:TextInput = new TextInput(); public var country:CountryComboBoxSimpleMXML = new CountryComboBoxSimpleMXML(); // Constructor public function AddressFormClass():void { super(); addEventListener(FlexEvent.CREATION_COMPLETE, creationCompleteHandler); } // Creation complete is a good time to add event listeners and // interact with child components. private function creationCompleteHandler(event:FlexEvent):void { submitButton.addEventListener(MouseEvent.CLICK, submitHandler); } // Gets called when the Submit button is clicked private function submitHandler(event:MouseEvent):void { // Gather the data for this form var addressVO:AddressVO = new AddressVO(); addressVO.name = nameInput.text; addressVO.street = street.text; addressVO.city = city.text; addressVO.state = state.text; addressVO.country = country.selectedItem as String; var submitEvent:AddressFormEvent = new AddressFormEvent(AddressFormEvent.SUBMIT); submitEvent.data = addressVO; // Dispatch an event to signal that the form has been submitted dispatchEvent(submitEvent); } } }
components/AddressForm.mxml
 
<?xml version="1.0" encoding="utf-8"?> <!-- AddressForm.mxml --> <custom:AddressFormClass 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:custom="components.*"> <mx:FormItem label="Name"> <mx:TextInput id="nameInput"/> </mx:FormItem> <mx:FormItem label="Street"> <mx:TextInput id="street"/> </mx:FormItem> <mx:FormItem label="City"> <mx:TextInput id="city"/> </mx:FormItem> <mx:FormItem label="State/County"> <mx:TextInput id="state"/> </mx:FormItem> <mx:FormItem label="Country"> <custom:CountryComboBoxSimpleMXML id="country"/> </mx:FormItem> <mx:Button id="submitButton" label="Submit"/> </custom:AddressFormClass>
components/AddressFormEvent.as
 
// components/AddressFormEvent.as package components { import flash.events.Event; import components.AddressVO; public class AddressFormEvent extends Event { public static const SUBMIT:String = "submit"; private var _data:AddressVO; public function AddressFormEvent( eventName:String ) { super ( eventName ); } public function set data(value:AddressVO):void { _data = value; } public function get data():AddressVO { return _data; } } }
components/AddressVO.as
 
// components/AddressVO.as package components { public class AddressVO { // We are using public properties for the // value object to keep this example short. In a // real-world application, make these properties // private and use implicit accessors to expose them // so you can do validation, etc. if necessary. public var name:String; public var street:String; public var city:String; public var state:String; public var country:String; } }
components/PaddedPanel.as
 
// components/PaddedPanel.as package components { import spark.components.Panel; public class PaddedPanel extends Panel { public function PaddedPanel() { // Call the constructor of the superclass. super(); // Set the border styles. setStyle("borderColor", "blue"); setStyle("dropShadowVisible", false); setStyle("cornerRadius", 20); } } }
components/CountryComboBoxSimpleMXML.mxml
 
<?xml version="1.0" encoding="utf-8"?> <!-- components/CountryComboBoxSimpleMXML.mxml --> <s:ComboBox xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx"> <s:dataProvider> <s:ArrayList> <fx:String>United States</fx:String> <fx:String>United Kingdom</fx:String> <!-- Add all other countries... --> </s:ArrayList> </s:dataProvider> </s:ComboBox>
components/ApplicationClass.as
 
// components/ApplicationClass.as package components { import components.AddressForm; import components.AddressFormEvent; import components.AddressVO; import flash.utils.describeType; import mx.controls.Alert; import mx.events.FlexEvent; import spark.components.Application; public class ApplicationClass extends Application { // Components in MXML public var addressForm:AddressForm; public function ApplicationClass() { super(); addEventListener (FlexEvent.CREATION_COMPLETE, creationCompleteHandler); } // // Event handlers // private function creationCompleteHandler(event:FlexEvent):void { // The custom AddressForm component dispatches a "submit" // event the form is submitted. Listen for this. addressForm.addEventListener(AddressFormEvent.SUBMIT, submitHandler); } private function submitHandler(event:AddressFormEvent):void { // Get the value object (data) from the event object var data:AddressVO = event.data as AddressVO; // Compose a string to display the contents of the value object to the user. var msg:String = "You submitted the following information: \r"; // Use the new introspection API and E4X to get a list of the properties // in the data object and enumerate over them to compose the string. var dataProperties:XMLList = describeType(data)..variable; for each (var i:XML in dataProperties) { var propertyName:String = i.@name; msg += i.@name + ": " + data[i.@name] + "\r"; } // Display the contents of the address form to the user. Alert.show(msg, "Thank you for submitting the form!"); } } }
 
Main application MXML file
<?xml version="1.0" encoding="utf-8"?> <!-- CodeBehind.mxml --> <custom:ApplicationClass 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:custom="components.*" width="400" height="310"> <custom:PaddedPanel title="Code Behind"> <custom:AddressForm id="addressForm"/> </custom:PaddedPanel> </custom:ApplicationClass>

 
For more information