Introduction
Adobe Flex provides a platform for developing Rich Internet applications (RIA). Adobe Flex is not one thing but it is a combination of various languages, frameworks and builders like MXML, Action Script, SDK and Flex Builder. For creating Adobe Flex applications, we use the markup language MXML which is similar to XML in syntax. Action Script is the scripting language that provides dynamic capabilities. The Adobe Flex SD includes a rich set of APIs for building complex user applications and finally Flex Builder is an IDE based on Eclipse base platform that provides developmental support for building applications.
also read:
Download and Install Adobe Flex
The following section describes where to download and how to install Flex environment for building Adobe applications. Trial version of Adobe Flex builder is available for download from Adobe site from here for a period of 60 days. At the time of writing this article, the version of Adobe Flex builder available is version 4. After downloading it, install the product by opening up the file ‘Set-up.exe’. Choose the option ‘Continue to use as a trial’ and then click with proceed to get the product installed. For running Adobe Flex applications, a web browser is required with Adobe Flash player support. For IE browser, the flash player ActiveX control can be downloaded from here. For Mozilla firefox, the Adobe Flash player plugin can be downloaded from here.
Once the installation process is done, launch the IDE to setup the default browser used for running Adobe Flex applications. Go to Window –> Preferences and then expand the ‘General’ tree item and select ‘Web Browser’. From here you can configure the default browser to be used for running Adobe Flex applications.
Writing the first Adobe Flex application
Launch the Adobe Flash builder IDE if it is not already opened. Click File –> New –> Other and then expand the folder ‘Flash Builder’ to select the item ‘Flex Project’ and click ‘Next’ to proceed.
Provide a meaningful project name like ‘Hello’. Make sure that the application type ‘Web (runs in Adobe Flash player)’ is selected and the application server type is selected as ‘None/Other’ in the Server technology group and click next.
Leave the default output folder to ‘bin-debug’ and click finish. By default, a file ‘Hello.mxml’ is created with the following contents.
<?xml version="1.0" encoding="utf-8"?> <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" minWidth="955" minHeight="600"> <fx:Declarations> <!-- Place non-visual elements (e.g., services, value objects) here --> </fx:Declarations> </s:Application>
As you can see the file ‘Hello.mxml’ contains the markup language. Edit the file in such a way that this file contains the following contents.
<?xml version="1.0" encoding="utf-8"?> <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" minWidth="500" minHeight="500" pageTitle="Hello World" backgroundColor="#A01A1A" width="600" height="400"> <s:Button label="Hello world from Adobe Flex" x="214" y="178" id="helloWorld" enabled="true" fontFamily="Arial" fontSize="15" color="#000000"> </s:Button> </s:Application>
As you can see from the above code snippet, the root tag should be ‘Application’ for any Adobe Flex application. The minimum height and width are configured through the attributes ‘minWidth’ and ‘maxWidth’. The text appearing in the title bar of a web page can be controlled through the attribute ‘pageTitle’. The code also makes use of the attributes ‘backgroundColor’, ‘width’ and ‘height’. We want to display the text ‘hello world’ in this application and we wanted to get the text displayed in a button. For this purpose, we have declared the component ‘Button’ originating from the namespace ‘library://ns.adobe.com/flex/spark’. Note that we have used the attribute label to specify the caption for the button. Positioning of the button is done through the co-ordinates ‘x’ and ‘y’. Later on, in this article, we will show how to make use of various layouts for positioning the controls in a more controlled fashion. We have also used other properties of the ‘Button’ component just to illustrate its usage.
Once this application is written, it has to be compiled with a compiler. Adobe Flex builder comes with a pre-configured Flex compiler for compiling Adobe Flex applications. The name of the compiler for compiling MXML applications is ‘mxmlc.exe’ (read as compiler for mxml). Command-line invocation of this compiler can also be done. Go to the folder ‘ADOBE_FLEX_BUILDER_INSTALL_HOME\ sdks\4.1.0\bin’, note that ‘ADOBE_FLEX_BUILDER_INSTALL_HOME’ represents the home directory where the Adobe Flex builder IDE got installed and the version ‘4.1.0’ may vary in your environment.
mxmlc PathToMxmlFile
However, this may not be required at all as the Adobe Flash builder IDE hides the complexities of compiling and running applications though a single click button. Click Ctrl+F11 to launch the application, this will open up the browser (as configured in the Preferences) .
Event Handling
In this section, we will illustrate event handling mechanism in Flex. Events are the corner-stones for any UI oriented applications and it is the mechanism of establishing communication between the user and an application. Events are signaled as a result of some trigger performed by the user such as the click on a button or a hyperlink, entering data in a text field etc. Having said that, there can be cases where events are auto-generated too. For example, it is quite common to fire a validation event when data is being entered in text fields. In Flex, it is the responsibility of components to register themselves to events; the target action to be taken after an event has happened is done through event handlers.
Consider the following login form that illustrates the various types of events and its usage.
<?xml version="1.0" encoding="utf-8"?> <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" minWidth="955" minHeight="600" width="544" height="200" applicationComplete="onCreationComplete(event)"> <fx:Script> <![CDATA[ import mx.controls.Alert; function loginHandler(event:Event){ Alert.show("Button clicked"); } function onKeyUp(event:Event){ Alert.show("KeyUp event emitted from " + event.target.toString()); } function onCreationComplete(event:Event){ Alert.show("Application initialization is completed"); } ]]> </fx:Script> <s:Label x="143" y="34" text="Enter your username and password" width="241" height="25" id="usernamePasswordLabel" verticalAlign="middle" textAlign="center" fontFamily="Times New Roman" fontSize="15" fontWeight="bold"/> <mx:Form x="144" y="62"> <mx:FormItem id="usernameLabel" label="Username:" required="true" x="68" y="32"> <s:TextInput id="userName" x="167" y="33" keyUp="onKeyUp(event)"> </s:TextInput> </mx:FormItem> <mx:FormItem id="passwordLabel" label="Password:" required="true" x="68" y="63"> <s:TextInput id="password" displayAsPassword="true" x="167" y="62" keyUp="onKeyUp(event)"> </s:TextInput> </mx:FormItem> <mx:FormItem> <s:Button id = "loginButton" label="Login" x="120" y="108" click="loginHandler(event)"> </s:Button> </mx:FormItem> </mx:Form> </s:Application>
The above application displays a login form that provides username and password capabilities along with a login button. To indicate that the components username/password belong to a form, the element ‘Form’ is used. The visual controls username, password and button are encapsulated as a combination of ‘FormItem’ and element that is specific to a control. Note that the above declaration dictates the usage of nested controls where for a form, we have a form item, and under a form item there can be text field or a button. Username and passwords must be mandatory, to denote this we have used the attribute ‘required’ for these controls which draws an asterisk (*) after the label names. This doesn’t mean that if someone didn’t enter any value for username/password, the validation will happen, this just provides an indication to the user of the application that the fields are mandatory. For a password field, the value entered by the user shouldn’t be displayed; instead the value should be masked with some pattern. To enable this support, the attribute ‘displayAsPassword’ is used which by default will mask the value entered by the user with ‘*’. Launching the application will bring up the browser similar to the following,
We have written event handlers for three different types of events – after the application initialization is complete, while entering data in the username and the text field components and when the user clicks the login button. Note that event handlers or any other Action script related programming has to be done within the ” block. Note that every event handler is written as a function that should take any implicit parameter of type ‘Event’. Also note how the formal parameter is used in the function declaration – the formal parameter name followed by its type, e.g event:Event. Within the implementation of the function, we have just alerted indicating that that particular event has happened through ‘Alert.show’.
Now that we have actually how event handlers can be written, it’s time to see how components are wired with events. The first event that occurs when the application initialization is complete is registered as part of the ‘Application’ declaration like the following,
<s:Application applicationComplete="onCreationComplete(event)">
Note that the event name ‘applicationComplete’ is registered for the event handler ‘onCreationComplete’. Similarly, handling key events for text-based components is done through ‘keyUp’ events and for handling click buttons (applicable for a Button components), the event name ‘click’ is used.
Validating data
It is quite normal to validate the data entered by the user in any form of application before submitting them. Adobe Flex provides rich validation support; the framework comes up with built-in support for many of the commonly used validators that can validate data available in the form of string, text, date etc. Given below is the list of commonly used validators available in Adobe Flex, note that the list is not exhaustive.
- String Validator
- Number Validator
- Date Validator
- Phone Number Validator
- Email Address Validator
- Currency Validator
- Credit Card Validator
- ZipCode Validator
The usage of validator will be illustrated in this section with an example. The example application prompts the user to input various user details like name, age, date of birth, sex, country, state, email id, phone number, credit card number etc.
Have a look at the following code for the above form.
<?xml version="1.0" encoding="utf-8"?> <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" minWidth="955" minHeight="600" pageTitle="Enter User details" backgroundColor="#B1A9A9"> <fx:Declarations> <mx:StringValidator id="nameValidator" source="{username}" property="text" minLength="4" maxLength="20" requiredFieldError="Name is mandatory." tooShortError="Name is too short. Enter value which is atleast 4 characters" tooLongError="Name value is too long. Enter value which is not more than 20 characters"/> <mx:NumberValidator id="ageValidator" source="{age}" property="text" minValue="1" maxValue="100" requiredFieldError="Age is mandatory" allowNegative="false"/> <mx:PhoneNumberValidator id="phoneNoValidator" source="{phoneNumber}" property="text" invalidCharError="Phone number is invalid" minDigits="8" requiredFieldError="Phone number is mandatory" wrongLengthError="Error in phone number length"/> <mx:EmailValidator id="emailValidator" source="{mailId}" property="text" invalidCharError="Email id contains invalid chars" missingAtSignError="@ sign is missing" missingPeriodInDomainError="Period sign is missing" missingUsernameError="Username is missing in email id" requiredFieldError="Email address is mandatory"/> <mx:CreditCardValidator id="ccValidator" source="{creditCardNo}" property="text" invalidCharError="CC contains invalid characters" requiredFieldError="CC is mandatory"/> <mx:ZipCodeValidator id="zipCodeValidator" source="{zipCode}" property="text" invalidCharError="Zip Code value is invalid" requiredFieldError="Zip Code is mandatory"/> </fx:Declarations> <s:Label x="267" y="10" text="Fill in the user details given below " height="24" width="311" id="userDetailsLabel" fontWeight="bold" verticalAlign="middle" textAlign="center" fontSize="18"/> <mx:Form height="383" x="267" y="57" backgroundColor="#E77070" width="311" id="userDetailsForm" label="User Details"> <mx:FormItem label="Name" required="true" x="68" y="32"> <s:TextInput id="username" x="167" y="33"> </s:TextInput> </mx:FormItem> <mx:FormItem label="Age:" required="true" x="68" y="63"> <s:TextInput id="age" x="167" y="62"> </s:TextInput> </mx:FormItem> <mx:FormItem label="Sex:" required="true"> <s:RadioButton label="Male" groupName="sex"/> <s:RadioButton label="Female" groupName="sex" width="81"/> </mx:FormItem> <mx:FormItem label="Date of Birth" required="true"> <s:TextInput id="dateOfBirth" x="167" y="62"> </s:TextInput> </mx:FormItem> <mx:FormItem label="Phone Number" required="true"> <s:TextInput id="phoneNumber" x="167" y="62"> </s:TextInput> </mx:FormItem> <mx:FormItem label="Email Id" required="true"> <s:TextInput id="mailId" x="167" y="62"> </s:TextInput> </mx:FormItem> <mx:FormItem label="Credit Card No" required="true"> <s:TextInput id="creditCardNo" x="167" y="62"> </s:TextInput> </mx:FormItem> <mx:FormItem label="Salary Per annum" required="true"> <s:TextInput id="salaryPerAnnum" x="167" y="62"> </s:TextInput> </mx:FormItem> <mx:FormItem label="Country" required="true"> <s:ComboBox id="country" x="167" y="62"> <s:ArrayList> <fx:String>India</fx:String> <fx:String>Australia</fx:String> <fx:String>Pakistan</fx:String> </s:ArrayList> </s:ComboBox> </mx:FormItem> <mx:FormItem label="State" required="true"> <s:ComboBox id="state" x="167" y="62"> <s:ArrayList> <fx:String>Tamil Nadu</fx:String> <fx:String>Karnataka</fx:String> </s:ArrayList> </s:ComboBox> </mx:FormItem> <mx:FormItem label="Zip Code" required="true"> <s:TextInput id="zipCode" x="167" y="62"> </s:TextInput> </mx:FormItem> </mx:Form> <s:Button label="Submit Details" id="submitDetails" x="363" y="461"/> </s:Application>
The section ” is used for defining the validators. Note that all the pre-built validators arise from the namespace ‘library://ns.adobe.com/flex/mx’ and hence the namespace prefix ‘mx’ (as declared) has to be used.
The general format for defining any validator is given below.
<mx:TypeOfValidator id="<IdForValidator>" source="{ComponentId}" property="PropertyOfAComponent"/>
In the above declaration, the type of validator represents the validator’s class type – e.g. StringValidator, NumericValidator etc. The attribute ‘id’ represents the unique identifier for a validator which can be made meaningful w.r.t to the component owning the validator. For example, to validate a ‘name’ field, we can give the value ‘nameValidator’ for the id attribute. The attribute ‘source’ binds the validator instance to be the component that requires validator and the value must be the identifier given for the component. For example, if the name field component is given a component id of ‘nameComponent’, then this value has to be given. A component will have multiple properties and which of the component’s property has to be validator can be given in the ‘property’ attribute, that said, it is very common to specify the property ‘text’ for text-based controls.
Have a look at the following declaration
<mx:StringValidator id="nameValidator" source="{username}" property="text" minLength="4" maxLength="20" requiredFieldError="Name is mandatory." tooShortError="Name is too short. Enter value which is atleast 4 characters" tooLongError="Name value is too long. Enter value which is not more than 20 characters"/>
In the above code snippet, we have defined the ‘StringValidator’ to validate on the ‘text’ property for the component ‘username’. The validation will be fired on this component when the component loses focus. Note that we have given the minimum and the maximum length for the field as 4 and 20 which means that if these constraints are violated, then the messages as configured in the properties ‘tooShortError’ and ‘tooLongError’ will be displayed. We have made the ‘username’ field as mandatory by defining the property ‘requiredFieldError’. Likewise, all validators have special properties specific to that validator.
Manipulating XML Data in Flex controls
In this section, we will see how to use XML as a data provider for various Flex controls. Flex provides a flexible API for dealing with various forms of XML data. We will also explore the various data types and the classes available in Flex for supporting XML for storing and retrieving data. Consider the following example,
<?xml version="1.0" encoding="utf-8"?> <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" minWidth="955" minHeight="600"> <fx:Declarations> <!-- Place non-visual elements (e.g., services, value objects) here --> </fx:Declarations> <fx:Script> <![CDATA[ private var employees:XML = <employees> <employee id = "1">John</employee> <employee id = "2">David</employee> <employee id = "3">Steve</employee> <employee id = "4">Marcus</employee> </employees>; private function displayXmlHandler(event:Event): void{ employeesTA.text = employees.toXMLString(); } private function clearXmlHandler(event:Event): void{ employeesTA.text = ""; } ]]> </fx:Script> <s:TextArea id = "employeesTA" x="274" y="159" width="304" height="163"/> <s:Button x="313" y="101" label="Display XML" click="displayXmlHandler(event)"/> <s:Button x="472" y="100" label="Clear XML" click="clearXmlHandler(event)"/> </s:Application>
Upon running the above example, it will provide an UI similar to the following in the browser.
The point to be noted is that a variable of type ‘XML’ is declared for storing XML data. The UI for this applications contains a text area along with the two buttons. The button ‘Display XML’ when clicked will try to display the xml content into the text area. The button ‘Clear XML’ does the reverse, i.e. it clears the xml data stored on the text area. For supporting the displaying and clearing of XML text onto the textarea, we have added two event handlers when the buttons are clicked.
The above example is fairly simple and straightforward, however the power of xml lies when it can be used as a data provider for complex Flex controls such as Datagrid. Consider the following example,
<?xml version="1.0" encoding="utf-8"?> <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" minWidth="955" minHeight="600"> <fx:Declarations> </fx:Declarations> <fx:Script> <![CDATA[ private var playersXmlData:XML = <players> <player id="SACHIN_TEN"> <name> <firstName>Sachin</firstName> <lastName>Tendulkar</lastName> </name> <playingFor>India</playingFor> <ODI>320</ODI> <Runs>16000</Runs> <Rating>1</Rating> </player> <player id="BR_LARA"> <name> <firstName>Brian</firstName> <lastName>Lara</lastName> </name> <playingFor>West Indies</playingFor> <ODI>200</ODI> <Runs>9000</Runs> <Rating>10</Rating> </player> <player id="RKY_PONTING"> <name> <firstName>Ricky</firstName> <lastName>Ponting</lastName> </name> <playingFor>Australia</playingFor> <ODI>260</ODI> <Runs>12000</Runs> <Rating>7</Rating> </player> </players>; private function getName(player:Object, column:DataGridColumn): String { var xml:XML = XML(player); return player.name.firstName + " "+ player.name.lastName; } ]]> </fx:Script> <mx:Panel title="Players Information" width="662" height="244" x="116" y="144" id="playersInfo" backgroundColor="#DB5C5C" contentBackgroundColor="#0B2973" borderColor="#000000" fontSize="20" fontStyle="normal" fontWeight="bold"> <mx:DataGrid id="playersGrid" dataProvider="{playersXmlData.player}" height="199" width="100%" variableRowHeight="true" fontSize="20"> <mx:columns> <mx:DataGridColumn headerText="Id" dataField="@id" color="#010101" fontFamily="Arial" fontSize="17" wordWrap="true" fontWeight="bold"/> <mx:DataGridColumn headerText="Name" labelFunction="getName" color="#010101" fontFamily="Arial" fontSize="17" wordWrap="true" fontWeight="bold"/> <mx:DataGridColumn headerText="Country" dataField="playingFor" color="#010101" fontFamily="Arial" fontSize="17" wordWrap="true" fontWeight="bold"/> <mx:DataGridColumn headerText="Total ODI Matches" dataField="ODI" color="#010101" fontFamily="Arial" fontSize="17" wordWrap="true" fontWeight="bold"/> <mx:DataGridColumn headerText="Total Runs in ODI" dataField="Runs" color="#010101" fontFamily="Arial" fontSize="17" wordWrap="true" fontWeight="bold"/> <mx:DataGridColumn headerText="ICC Rating" dataField="Rating" color="#010101" fontFamily="Arial" fontSize="17" wordWrap="true" fontWeight="bold"/> </mx:columns> </mx:DataGrid> </mx:Panel> </s:Application>
The scripting block for this application contains the declaration of XML that contains various details of some players. Then after that we draw a panel using ‘mx:Panel’ element for holding the Grid component. We have expressed the title for the Panel through the attribute ‘title’. The data source for the grid component comes from the ‘players xml’ and hence the attribute ‘dataProvider’ is used to specify this. A data grid is expected to contain a series of columns with static information (in the form of heading) and dynamic information. These details are expressed through the elements ‘mx:columns’ and ‘mx:DataGridColumn’. For displaying the static header text we have used the attribute ‘headerText’.
We have used three different ways for extracting information from the XML in this example. The first way is for referring the attributes. For attributes, the attribute name has to be prefixed with ‘@’ symbol. For example, ‘id’ appears to be an attribute and the same has been referred as ‘@id’ in the dataField of the grid component. Referring child elements are straightforward, the child element name can appear directly in the dataField attribute. The final way for fetching information to be displayed is to have a special type of function that operates/aggregates data from the complex xml element. For example, in order to display the name of the player which appears as two child elements ‘firstName’ and ‘lastName’, we have define a function ‘getName()’ which returns the combined value of the child element ‘firstName’ and ‘lastName’. Note the first argument passed to the function is the current player object and the second argument is the column object. Within the implementation of the function, we have returned the player’s complete name by taking the first and the last name into consideration.
Formatting Data
In this section, we will see how to format the data before displaying it. Like Validators, Adobe Flex comes with a set of formatters that suits the basic needs. For example, it provides formatters for formatting numbers, currency, phone number, date etc. Have a look at the following code that makes use of the formatters.
<?xml version="1.0" encoding="utf-8"?> <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" minWidth="955" minHeight="600"> <fx:Declarations> <mx:NumberFormatter id="numberFormatter" useNegativeSign="true" precision="3" error="The format of the number is incorrect"> </mx:NumberFormatter> <mx:CurrencyFormatter id="currencyFormatter" currencySymbol="Rs " useNegativeSign="true" error="The format of currency is incorrect"> </mx:CurrencyFormatter> <mx:DateFormatter id="dateFormatter" error="Date format is incorrect" formatString="MM/DD/YYYY"> </mx:DateFormatter> <mx:PhoneFormatter id="phoneFormatter" error="Phone format is invalid" formatString="### - #### ####"> </mx:PhoneFormatter> </fx:Declarations> <fx:Script> <![CDATA[ private var textXML:XML = <Data> <Number>-10.123243</Number> <Currency>803432.323</Currency> <Date>01/01/10 10:33</Date> <Phone>08041413131</Phone> </Data>; ]]> </fx:Script> <s:Panel x="80" y="148" width="675" height="236" id="formatterId" title="Formatter Test"> <s:Label text="Currency: Original Value -> {textXML.Currency}, Formatted Value -> {currencyFormatter.format(textXML.Currency)}" x="7" y="24" height="30" fontWeight="bold" width="616"/> <s:Label text="Number: Original Value -> {textXML.Number}, Formatted Value -> {numberFormatter.format(textXML.Number)}" x="10" y="62" height="28" width="613" fontWeight="bold"/> <s:Label text="Date: Original Value -> {textXML.Date}, Formatted Value -> {dateFormatter.format(String(textXML.Date))}" x="10" y="121" height="28" width="613" fontWeight="bold"/> <s:Label text="Phone: Original Value -> {textXML.Phone}, Formatted Value -> {phoneFormatter.format(textXML.Phone)}" x="10" y="157" height="28" width="613" fontWeight="bold"/> </s:Panel> </s:Application>
Like the usage of validators, formatters are declared within the ‘fx:Declarations’ section. We have used ‘NumberFormatter’, ‘CurrencyFormatter’, DateFormatter’ and ‘PhoneFormatter’ for formatting numbers, currency, date and phone numbers respectively. Later on in the ‘fx:Script’ block, we have created some sample data to be formatted which were later referred in the UI components. Note that for performing the formatting operation, we have to call the format() method by passing in the data to be formatted. We have used the label component for displaying the value before formatting and the value that got modified after formatting. Running the above program will result in an output similar to the following.
Conclusion
In this article, we saw an introduction to the basic level of programming in Adobe Flex. The article initially started with explaining how to setup the Adobe Flex environment with the introduction to Adobe Flex Builder and Adobe Flash player plugins. Later on, it showed how to write a simple ‘Hello World’ application. Then the event handler mechanism along with process of validating data were discussed in detail. It was then followed by the usage of XML data along with the complex Grid components with respect to data binding. Finally the article concluded with the usage of Formatters for formatting data.