MX Form, FormHeading, and FormItem layout containers

Forms are one of the most common methods that web applications use to collect information from users. Forms are used for collecting registration, purchase, and billing information, and for many other data collection tasks.

Note: Adobe recommends that, when possible, you use the Spark Form container instead of the MX Form container. For more information, see The Spark Form, Spark FormHeading, and Spark FormItem containers.

About forms

Flex supports form development by using the Form layout container and several child components of the Form container. The Form container lets you control the layout of a form, mark form fields as required or optional, handle error messages, and bind your form data to the Flex data model to perform data checking and validation. Also, you can apply style sheets to configure the appearance of your forms.

You use three different components to create your forms, as the following example shows:

Form container
A.
Form container

B.
FormHeading control

C.
FormItem containers

For complete reference information, see Form, FormHeading, and FormItem in the ActionScript 3.0 Reference for the Adobe Flash Platform.

Creating forms

You typically create a form by defining the following elements:

  • The Form control

  • FormHeading components, nested inside the Form control

  • FormItem containers, nested inside the Form control

  • Form fields, such as ComboBox and TextInput controls, nested inside the FormItem containers

    You can also include other components inside a form, such as HRule controls, as needed.

Creating the Form container

The Form container is the outermost container of a Flex form. The primary use of the Form container is to control the sizing and layout of the contents of the form, including the size of labels and the gap between items. The Form container always arranges its children vertically and left-aligns them in the form. The form container contains one or more FormHeading and FormItem containers.

You use the <mx:Form> tag to define the Form container. Specify an id value if you intend to refer to the entire form elsewhere in your MXML, either in another tag or in an ActionScript block.

The following code example shows the Form container definition for the form shown in the previous image in About forms:

<?xml version="1.0"?>
<!-- containers\layouts\FormSimple.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark">

    <mx:Form id="myForm" width="400" height="100">

        <!-- Define FormHeading and FormItem components here -->

    </mx:Form>
</s:Application>

For complete reference information, see the ActionScript 3.0 Reference for the Adobe Flash Platform.

Creating a FormHeading control

A FormHeading control specifies an optional label for a group of FormItem containers. The left side of the label is aligned with the left side of the controls in the form. You can have multiple FormHeading controls in your form to designate multiple content areas. You can also use FormHeading controls with a blank label to create vertical space in your form.

You use the <mx:FormHeading> tag to define a FormHeading container. Specify an id value if you intend to refer to the heading elsewhere in your MXML, either in another tag or in an ActionScript block.

The following code example defines the FormHeading control for the image shown in About forms:

<?xml version="1.0"?>
<!-- containers\layouts\FormHeadingSimple.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark">

    <mx:Form id="myForm" width="400" height="100">

        <mx:FormHeading label="Billing Information"/>

        <!--Define FormItem containers here. -->

    </mx:Form>
</s:Application>

The executing SWF file for the previous example is shown below:

For complete reference information, see the ActionScript 3.0 Reference for the Adobe Flash Platform.

Creating a FormItem container

A FormItem container specifies a form element consisting of the following parts:

  • A single label

  • One or more child controls or containers, such as input controls

    The label is vertically aligned with the first child in the FormItem container and is right-aligned in the region to the left of the container.

    You use the <mx:FormItem> tag to define a FormItem container. Specify an id value if you intend to refer to the item elsewhere in your MXML, either in another tag or in an ActionScript block.

    Form containers typically contain multiple FormItem containers, as the following example shows:

    Form containers containing multiple FormItem containers

    In this example, you define three FormItem containers: one with the label First Name, one with the label Last Name, and one with the label Address. The Address FormItem container holds two controls to let a user enter two lines of address information. Each of the other two FormItem containers includes a single control.

    For complete reference information, see FormItem in the ActionScript 3.0 Reference for the Adobe Flash Platform.

Specifying form item direction

When you create a FormItem container, you specify its direction by using the value vertical (default) or horizontal for the direction property:

vertical
Flex positions children vertically to the right of the FormItem label.

horizontal
Flex positions children horizontally to the right of the FormItem label. If all children do not fit on a single row, they are divided into multiple rows with equal-sized columns. You can ensure that all children fit on a single line by using percentage-based widths or by specifying explicit widths wide enough for all of the components.

Controlling form item label style

You control the style of a FormItem label by setting the labelStyleName style property. The following example sets the FormItem label color to dark blue and its font size to 20 pixels:

<?xml version="1.0"?>
<!-- containers\layouts\FormItemStyle.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark">

    <fx:Style>
        .myFormItemLabelStyle {
            color: #333399;
            fontSize: 20;
         }
         
    </fx:Style>

    <fx:Script>
        <![CDATA[
            private function processValues(zip:String, pn:String):void {
                // Validate and process data.
            }
        ]]>
    </fx:Script>

    <mx:Form id="myForm" defaultButton="{mySubmitButton}">

        <mx:FormItem label="Zip Code" 
            labelStyleName="myFormItemLabelStyle">
            <mx:TextInput id="zipCode"/>
        </mx:FormItem>
        <mx:FormItem label="Phone Number">
            <mx:TextInput id="phoneNumber"/>
        </mx:FormItem>
    
        <mx:FormItem>
            <mx:Button label="Submit" id="mySubmitButton" 
                click="processValues(zipCode.text, phoneNumber.text);"/>
        </mx:FormItem>
    
    </mx:Form>
</s:Application>

The executing SWF file for the previous example is shown below:

Example: A simple form

The following example shows the FormItem container definitions for the example form:

<?xml version="1.0"?>
<!-- containers\layouts\FormComplete.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark">

    <fx:Script>
        <![CDATA[
            private function submitForm():void { 
                // Handle the form submission.
            }
        ]]>
    </fx:Script>

    <mx:Form id="myForm" width="400">

        <mx:FormHeading label="Billing Information"/>

        <mx:FormItem label="First Name">
            <mx:TextInput id="fname" width="100%"/>
        </mx:FormItem>

        <mx:FormItem label="Last Name">
            <mx:TextInput id="lname" width="100%"/>
        </mx:FormItem>

        <mx:FormItem label="Address">
            <mx:TextInput id="addr1" width="100%"/>
            <mx:TextInput id="addr2" width="100%"/>
        </mx:FormItem>

        <mx:FormItem label="City / State" direction="vertical">
            <mx:TextInput id="city"/>
            <mx:ComboBox id="st" width="75">
              <mx:ArrayList>
                 <fx:String>MA</fx:String>
                 <fx:String>NH</fx:String>
                 <fx:String>RI</fx:String>
              </mx:ArrayList>                     
            </mx:ComboBox>
        </mx:FormItem>

        <mx:FormItem label="ZIP Code">
            <mx:TextInput id="zip" width="100"/>
        </mx:FormItem>

        <mx:FormItem label="Country">
            <mx:ComboBox id="cntry">
              <mx:ArrayList>
                 <fx:String>USA</fx:String>
                 <fx:String>UAE</fx:String>
                 <fx:String>UAW</fx:String>
              </mx:ArrayList>                     
            </mx:ComboBox>
        </mx:FormItem>

        <mx:FormItem>
            <mx:HRule width="200" height="1"/>
            <mx:Button label="Submit Form" click="submitForm();"/>
        </mx:FormItem>
    </mx:Form>
</s:Application>

The executing SWF file for the previous example is shown below:

Laying out forms

Flex determines the default size of a form in the following ways:

  • The default height is large enough to hold the default or explicit heights of all the container children, plus the Form container top and bottom padding and the gaps between children.

  • The default width is large enough to accommodate the widest FormItem label, plus the indicatorGap between the labels and the child controls, plus the widest default or explicit width among the child controls in the FormItems.

Aligning and spacing Form container children

All Form container labels are right-aligned, and all children are left-aligned in the container. You cannot override this alignment.

The following example shows the spacing of Form container children that you can control:

Spacing of Form container children
A.
Form container: labelWidth

B.
Form container: verticalGap = 6

C.
FormItem container: verticalGap = 6

D.
Form container: indicatorGap = 14

The following table describes the style properties that you use to control spacing and their default values:

Component

Style

Description

Default value

Form

verticalGap

Vertical space between Form container children

6 pixels

horizontalGap

Horizontal space between Form container children

8 pixels

labelWidth

Width of labels

Calculated by the container based on the child labels

paddingTop 
paddingBottom 
paddingLeft 
paddingRight

Border spacing around children

16 pixels on all sides

indicatorGap

Gap between the end of the area in the form reserved for labels and the FormItem children or FormHeading heading

14 pixels

FormHeading

indicatorGap

Overrides the indicator gap set by the <mx:Form> tag

14 pixels

paddingTop

Gap between the top of the component and the label text

16 pixels

FormItem

direction

Direction of FormItem children: vertical or horizontal

vertical

horizontalGap

Horizontal spacing between children in a FormItem container

8 pixels

labelWidth

The width for the FormItem heading

The width of the label text

paddingTop 
paddingBottom 
paddingLeft 
paddingRight

Border spacing around the FormItem

0 pixels on all sides

verticalGap

Vertical spacing between children in a FormItem container

6 pixels

indicatorGap

Overrides the indicator gap set by the <mx:Form> tag

Determined by the <mx:Form> tag

Sizing and positioning Form container children

The Form layout container arranges children in a vertical column. The area of the Form container that is designated for children does not encompass the entire Form container. Instead, it starts at the right of the area defined by any labels and the gap defined by the indicatorGap property. For example, if the width of the Form container is 500 pixels, and the labels and indicatorGap property allocate 100 pixels of that width, the width of the child area is 400 pixels.

By default, Flex sizes the Form layout children vertically to their default height. Flex then determines the default width of each child, and stretches the child’s width to the next highest quarter of the child area—that is, to one-quarter, one-half, three-quarters, or full width of the child area.

For example, if a container has a child area 400 pixels wide, and the default width of a TextArea control is 125 pixels, Flex stretches the TextArea control horizontally to the next higher quarter of the child area, the 200-pixel boundary, which is one-half of the child area. This sizing algorithm applies only to components without an explicitly specified width. It prevents your containers from having ragged right edges caused by controls with different widths.

You can also explicitly set the height or width of any control in the form to either a pixel value or a percentage of the Form size by using the height and width properties of the child.

Defining a default button

You use the defaultButton property of a container to define a default Button control. Pressing the Enter key while the focus is on any form control activates the Button control just as if it was explicitly selected.

For example, a login form displays user name and password inputs and a submit Button control. Typically, the user types a user name, tabs to the password field, types the password, and presses the Enter key to submit the login information without explicitly selecting the Button control. To define this type of interaction, set the defaultButton to the id of the submit Button control. In the following example, the event listener for the click event of submit button displays an Alert control, to show that Flex triggers this event if the user presses the Enter key when any form field has the focus. The commented-out line in the example would perform the more realistic action of invoking a web service to let the user log in.

<?xml version="1.0"?>
<!-- containers\layouts\FormDefButton.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark">

    <fx:Script> 
        <![CDATA[
            import flash.events.MouseEvent;
            import mx.controls.Alert;
    
            private function submitLogin(eventObj:MouseEvent):void {
                // Display an Alert to show the event happened.
                Alert.show("Login Requested");
                // Commented out to work without a web service.
                //myWebService.Login.send();
            }   
        ]]>
    </fx:Script>

    <mx:Form defaultButton="{mySubmitButton}">
        <mx:FormItem label="Username">
            <mx:TextInput id="username" 
                width="100"/>
        </mx:FormItem>
        <mx:FormItem label="Password">
            <mx:TextInput id="password" 
                width="100" 
                displayAsPassword="true"/>
        </mx:FormItem>
        <mx:FormItem>
            <mx:Button id="mySubmitButton" 
                label="Login" 
                click="submitLogin(event);"/>
        </mx:FormItem>
    </mx:Form>
</s:Application>

The executing SWF file for the previous example is shown below:

Note: When the drop-down list of a ComboBox control is open, pressing Enter selects the currently highlighted item in the ComboBox control; it does not activate the default button.

Specifying required fields

Flex includes support for defining required input fields of a form. To define a required field, you specify the required property of the FormItem container. If this property is specified, all the children of the FormItem container are marked as required.

Flex inserts a red asterisk (*) character as a separator between the FormItem label and the FormItem child to indicate a required field. For example, the following example shows an optional ZIP code field and a required ZIP code field:

A required ZIP code field

The following code example defines these fields:

<?xml version="1.0"?>
<!-- containers\layouts\FormReqField.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark">

    <mx:Form>
        <mx:FormItem label="ZIP Code">
            <mx:TextInput id="zipOptional" 
                width="100"/>
        </mx:FormItem>

        <mx:FormItem label="ZIP Code" required="true">
            <mx:TextInput id="zipRequired" 
                width="100"/>
        </mx:FormItem>
    </mx:Form>
</s:Application>

The executing SWF file for the previous example is shown below:

You can enable the required indicator of a FormItem child at run time. This could be useful when the user input in one form field makes another field required. For example, you might have a form with a CheckBox control that the user selects to subscribe to a newsletter. Checking the box could make the user e-mail field required, as the following example shows:

<?xml version="1.0"?>
<!-- containers\layouts\FormReqFieldRuntime.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark">

    <mx:Form>
        <mx:FormItem label="Subscribe">
            <mx:CheckBox label="Subscribe?" 
                click="emAddr.required=!emAddr.required;"/>
        </mx:FormItem>

        <mx:FormItem id="emAddr" label="E-mail Address">
            <mx:TextInput id="emailAddr"/>
        </mx:FormItem>
    </mx:Form>
</s:Application>

The executing SWF file for the previous example is shown below:

Flex does not perform any automatic enforcement of a required field; it only marks fields as required. You must add validation logic to your form to enforce it. As part of your enforcement logic, you can use Flex validators. All Flex validators have a required property, which is true by default. You can use validators in several ways, depending on how you enforce required fields and validation. For details, see Validating Data.

Storing and validating form data

As part of designing your form, you must consider how you want to store your form data. In Flex, you have the following choices.

  • Store the data within the form controls.

  • Create a Flex data model to store your data.

Your decision about how to represent your data also affects how you perform input error detection or data validation, one of the primary tasks of a robust and stable form. You typically validate user input before you submit the data to the server. You can validate the user input within a submit function, or when a user enters data into the form.

Flex provides a set of data validators for the most common types of data collected by a form. You can use Flex validators with the following types of data:

  • Credit card information

  • Dates

  • E-mail addresses

  • Numbers

  • Phone numbers

  • Social Security Numbers

  • Strings

  • ZIP codes

As part of building your form, you can perform data validation by using your own custom logic, take advantage of the Flex data validation mechanism, or use a combination of custom logic and Flex data validation.

The following sections include information on how to initiate validation in a form; for detailed information on how to use Flex data validation, see Validating Data.

Using Form controls to hold your form data

The following example uses Form controls to store the form data:

<?xml version="1.0"?>
<!-- containers\layouts\FormData.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark">

    <fx:Script>
        <![CDATA[
            private function processValues(zip:String, pn:String):void {
                // Validate and process data.
            }
        ]]>
    </fx:Script>

    <mx:Form id="myForm" defaultButton="{mySubmitButton}">

        <mx:FormItem label="ZIP Code">
            <mx:TextInput id="zipCode"/>
        </mx:FormItem>
        <mx:FormItem label="Phone Number">
            <mx:TextInput id="phoneNumber"/>
        </mx:FormItem>
    
        <mx:FormItem>
            <mx:Button label="Submit" id="mySubmitButton" 
                click="processValues(zipCode.text, phoneNumber.text);"/>
        </mx:FormItem>
    
    </mx:Form>
</s:Application>

The executing SWF file for the previous example is shown below:

This example form defines two form controls: one for a ZIP code and one for a phone number. When you submit the form, you call a function that takes the two arguments that correspond to the data stored in each control. Your submit function can then perform any data validation on its inputs before processing the form data.

You don’t have to pass the data to the submit function. The submit function can access the form control data directly, as the following example shows:

<?xml version="1.0"?>
<!-- containers\layouts\FormDataSubmitNoArg.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark">

    <fx:Script>
        <![CDATA[
            private function processValues():void {
                var inputZip:String = zipCode.text;
                var inputPhone:String = phoneNumber.text;
                // Check to see if pn is a number.
                // Check to see if zip is less than 4 digits.
                // Process data.
            }
        ]]>
    </fx:Script>

    <mx:Form id="myForm" defaultButton="{mySubmitButton}">

        <mx:FormItem label="ZIP Code">
            <mx:TextInput id="zipCode"/>
        </mx:FormItem>
        <mx:FormItem label="Phone Number">
            <mx:TextInput id="phoneNumber"/>
        </mx:FormItem>
    
        <mx:FormItem>
            <mx:Button label="Submit" id="mySubmitButton" 
                click="processValues();"/>
        </mx:FormItem>
    
    </mx:Form>
</s:Application>

The executing SWF file for the previous example is shown below:

The technique of using the form fields directly, however, has the problem that the function is specific to the form and cannot easily be used by other forms.

Validating form control contents data on user entry

To validate form data upon user input, you can add Flex data validators to your application. The following example uses the ZipCodeValidator and PhoneNumberValidator to perform validation.

<?xml version="1.0"?>
<!-- containers\layouts\FormDataValidate.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark">

    <fx:Script>
        <![CDATA[
            private function processValues():void {
                var inputZip:String = zipCode.text;
                var inputPhone:String = phoneNumber.text;
                // Perform any additional validation.
                // Process data.
            }
        ]]>
    </fx:Script>

    <fx:Declarations>
        <mx:ZipCodeValidator id="zcVal"
            source="{zipCode}" property="text" 
            domain="US or Canada"/>
        <mx:PhoneNumberValidator id="pnVal" 
            source="{phoneNumber}" property="text"/>
    </fx:Declarations>
        
    <mx:Form id="myForm" defaultButton="{mySubmitButton}">
        <mx:FormItem label="ZIP Code">
            <mx:TextInput id="zipCode"/>
        </mx:FormItem>
        <mx:FormItem label="Phone Number">
            <mx:TextInput id="phoneNumber"/>
        </mx:FormItem>
    
        <mx:FormItem>
            <mx:Button label="Submit" id="mySubmitButton" 
                click="processValues();"/>
        </mx:FormItem>
    </mx:Form>
</s:Application>

The executing SWF file for the previous example is shown below:

If you validate the input data every time the user enters it, you might not have to do so again in your submit function. However, some validation in your submit function might still be necessary, especially if you want to ensure that two fields are valid when compared with each other.

For example, you can use Flex validators to validate a ZIP code field and state field individually. But you might want to validate that the ZIP code is valid for the specified state before submitting the form data. To do so, you perform a second validation in the submit function.

For detailed information on using validators, see Validating Data.

Using a Flex data model to store form data

You can use a Flex data model to structure and store your form data and provide a framework for data validation. A data model stores data in fields that represent each part of a specific data set. For example, a person model might store information such as a person’s name, age, and phone number. You can then validate the data in the model based on the type of data stored in each model field.

The following example defines a Flex data model that contains two values. The two values correspond to the two input fields of a form.

<?xml version="1.0"?>
<!-- containers\layouts\FormDataModel.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark">

    <!-- Define the submit function that validates and 
        processes the data. -->
    <fx:Script>
        <![CDATA[
            private function processValues():void {
                var inputZip:String = myFormModel.zipCodeModel;
                var inputPhone:String = myFormModel.phoneNumberModel;
                // Process data.
            }
        ]]>
    </fx:Script>

    <fx:Declarations>
        <!-- Define data model. -->
        <fx:Model id="myFormModel">
            <info>
                <zipCodeModel>{zipCode.text}</zipCodeModel>
                <phoneNumberModel>{phoneNumber.text}</phoneNumberModel>
            </info>
        </fx:Model>
    </fx:Declarations>

    <!-- Define the form. -->
    <mx:Form borderStyle="solid">
        <mx:FormItem label="ZIP Code">
            <mx:TextInput id="zipCode"/>
        </mx:FormItem>
        <mx:FormItem label="Phone Number">
            <mx:TextInput id="phoneNumber"/>
        </mx:FormItem>
        <mx:FormItem>
            <mx:Button id="b1" 
                label="Submit" 
                click="processValues();"/>
        </mx:FormItem>
    </mx:Form>
</s:Application>

The executing SWF file for the previous example is shown below:

You use the <fx:Model> tag to define the data model. Each child tag of the data model defines one field of the model. The tag body of each child tag in the model defines a binding to a form control. In this example, you bind the zipCodeModel model field to the text value of the zipCode TextInput control, and you bind the phoneNumberModel field to the text value of the phoneNumber TextInput control. For more information on data models, see Storing data.

When you bind a control to a data model, Flex automatically copies data from the control to the model upon user input. In this example, your submit function accesses the data from the model, not directly from the form controls.

Using Flex validators with form models

The following example modifies the example in the previous section by inserting two data validators—one for the ZIP code field and one for the phone number field:

<?xml version="1.0"?>
<!-- containers\layouts\FormDataModelVal.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark">

    <!-- Define the submit function that validates and processes the data -->
    <fx:Script>
        <![CDATA[
            private function processValues():void {
                var inputZip:String = myFormModel.zipCodeModel;
                var inputPhone:String = myFormModel.phoneNumberModel;
                // Process data.
            }
        ]]>
    </fx:Script>

    <fx:Declarations>
        <!-- Define data model. -->
        <fx:Model id="myFormModel">
            <info>
                <zipCodeModel>{zipCode.text}</zipCodeModel>
                <phoneNumberModel>{phoneNumber.text}</phoneNumberModel>
            </info>
        </fx:Model>

        <!-- Define validators. -->
        <mx:ZipCodeValidator 
            source="{myFormModel}" property="zipCodeModel"
            trigger="{zipCode}" 
            listener="{zipCode}"/>
        <mx:PhoneNumberValidator 
            source="{myFormModel}" property="phoneNumberModel" 
            trigger="{b1}" 
            listener="{phoneNumber}"
            triggerEvent="click"/>
    </fx:Declarations>

    <!-- Define the form. -->
    <mx:Form borderStyle="solid">
        <mx:FormItem label="ZIP Code">
            <mx:TextInput id="zipCode"/>
        </mx:FormItem>
        <mx:FormItem label="Phone Number">
            <mx:TextInput id="phoneNumber"/>
        </mx:FormItem>
        <mx:FormItem>
            <mx:Button id="b1" 
                label="Submit" 
                click="processValues();"/>
        </mx:FormItem>
    </mx:Form>
</s:Application>

The executing SWF file for the previous example is shown below:

When the user enters data into the zipCode form field, Flex automatically copies that data to the data model. The ZipCodeValidator validator gets invoked when the user exits the zipCode form field, as specified by the validator’s trigger property and the default value of the triggerEvent property, valueCommit. Flex then draws a red box around the zipCode field, as specified by the listener property.

When the user enters data into the phoneNumber form field, Flex automatically copies that data to the data model. The PhoneNumberValidator validator gets invoked when the user clicks the Button control, as specified by the validator’s trigger and triggerEvent properties. Flex then draws a red box around the phoneNumber field, as specified by the listener property.

For detailed information on using validators, see Validating Data.

Populating a Form control from a data model

Another use for data models is to include data in the model to populate form fields with values. The following example shows a form that reads static data from a data model to obtain the value for a form field:

<?xml version="1.0"?>
<!-- containers\layouts\FormDataFromModel.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark">

    <fx:Declarations>
        <!-- Define data model. -->
        <fx:Model id="myFormModel">
            <info>
                <fName>{firstName.text}</fName>
                <lName>{lastName.text}</lName>
                <department>Accounting</department>
            </info>
        </fx:Model>
    </fx:Declarations>

    <mx:Form>
        <mx:FormItem label="First and Last Names">
            <mx:TextInput id="firstName"/>
            <mx:TextInput id="lastName"/>
        </mx:FormItem>
        <mx:FormItem label="Department">
            <mx:TextInput id="dept" text="{myFormModel.department}"/>
        </mx:FormItem>
    </mx:Form>
</s:Application>

The executing SWF file for the previous example is shown below:

This department data is considered static because the form always shows the same value in the field. You could also create a dynamic data model that takes the value of the department field from a web service, or calculates it based on user input.

For more information on data models, see Storing data.

Submitting data to a server

Form data is typically processed on a server, not locally on the client. Therefore, the submit event listener must have a mechanism for packing the form data for transfer to the server, and then handling any results returned from the server. In Flex, you typically use a web service, HTTP service, or remote Java object to pass data to the server.

You can also build logic into your submit function to control navigation of your application when the submit succeeds and when it fails. When the submit succeeds, you typically navigate to an area of your application that displays the results. If the submit fails, you can return control to the form so that the user can fix any errors.

The following example adds a web service to process form input data. In this example, the user enters a ZIP code, and then selects the Submit button. After performing any data validation, the submit event listener calls the web service to obtain the city name, current temperature, and forecast for the ZIP code.

<?xml version="1.0"?>
<!-- containers\layouts\FormDataSubmitServer.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark">
    <s:layout>
        <s:VerticalLayout/>
    </s:layout>

    <fx:Script>
        <![CDATA[
            private function processValues():void {
                // Check to see if ZIP code is valid.
                WeatherService.GetWeather.send();
            }
        ]]>
    </fx:Script>

    <fx:Declarations>
        <!-- Define the web service connection. 
            The specified WSDL URI is not functional. -->
        <mx:WebService id="WeatherService" 
            wsdl="/ws/WeatherService?wsdl">  
            <mx:operation name="GetWeather">
                <mx:request>
                    <ZipCode>{zipCode.text}</ZipCode>
                </mx:request>
            </mx:operation>
        </mx:WebService>
    </fx:Declarations>

    <mx:Form>
        <mx:FormItem label="ZIP Code">
            <mx:TextInput id="zipCode" 
                width="200" 
                text="ZIP code please."/>
            <mx:Button 
                width="60" 
                label="Submit" 
                click="processValues();"/>
        </mx:FormItem>
    </mx:Form>

    <mx:VBox>
        <mx:TextArea
            text=
              "{WeatherService.GetWeather.lastResult.CityShortName}"/>
        <mx:TextArea 
            text=
              "{WeatherService.GetWeather.lastResult.CurrentTemp}"/>
        <mx:TextArea 
            text=
          "{WeatherService.GetWeather.lastResult.DayForecast}"/>
    </mx:VBox>
</s:Application>

This example binds the form’s input zipCode field directly to the ZipCode field of the web service request. To display the results from the web service, you bind the results to controls in a VBox container.

You have a great deal of flexibility when passing data to a web service. For example, you might modify this example to bind the input form field to a data model, and then bind the data model to the web service request. For more information on using web services, see Accessing server-side data.

You can also add event listeners for the web service to handle both a successful call to the web service, by using the result event, and a call that generates an error, by using the fault event. An error condition might cause you to display a message to the user with a description of the error. For a successful result, you might navigate to another section of your application.

The following example adds a result event and a fault event to the form. In this example, the form is defined as one child of a ViewStack container, and the form results are defined as a second child of the ViewStack container:

<?xml version="1.0"?>
<!-- containers\layouts\FormDataSubmitServerEvents.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark">

    <fx:Script>
        <![CDATA[
            import mx.controls.Alert;

            private function processValues():void {
                // Check to see if ZIP code is valid.
                WeatherService.GetWeather.send();
            }
    
            private function successfulCall():void {
                vs1.selectedIndex=1;
            }
    
            private function errorCall():void {
                Alert.show("Web service failed!", "Alert Box", Alert.OK);
            }
        ]]>
    </fx:Script>

    <fx:Declarations>
        <!-- Define the web service connection. 
            The specified WSDL URI is not functional. -->
        <mx:WebService id="WeatherService"
            wsdl="/ws/WeatherService?wsdl"  
            result="successfulCall();" 
            fault="errorCall();">   
            <mx:operation name="GetWeather">
                <mx:request>
                    <ZipCode>{zipCode.text}</ZipCode>
                </mx:request>
            </mx:operation>
        </mx:WebService>
    </fx:Declarations>

    <mx:ViewStack id="vs1">
        <mx:Form>
            <mx:FormItem label="ZIP Code">
                <mx:TextInput id="zipCode" 
                    width="200" 
                    text="ZIP code please."/>
                <mx:Button width="60" 
                    label="Submit" 
                    click="processValues();"/>
            </mx:FormItem>
        </mx:Form>
    
        <mx:VBox>
            <mx:TextArea
                text=
                    "{WeatherService.GetWeather.lastResult.CityShortName}"/>
            <mx:TextArea 
                text=
                    "{WeatherService.GetWeather.lastResult.CurrentTemp}"/>
            <mx:TextArea 
                text=
                    "{WeatherService.GetWeather.lastResult.DayForecast}"/>
        </mx:VBox>
    </mx:ViewStack>
</s:Application>

When a call to the web service succeeds, the successfulCall() function switches the current ViewStack child to the VBox container to show the returned results. An error from the web service displays an Alert box, but does not change the current child of the ViewStack container; the form remains visible, which lets the user fix any input errors.

You have many options for handling navigation in your application based on the results of the submit function. The previous example used a ViewStack container to handle navigation. You might also choose to use a TabNavigator container or Accordion container for this same purpose.

In some applications, you might choose to embed the form in a TitleWindow container. A TitleWindow container is a pop-up window that appears above the Adobe Flash Player drawing surface. In this scenario, users enter form data and submit the form from the TitleWindow container. If a submit succeeds, the TitleWindow container closes and displays the results in another area of your application. If a submit fails, Flex displays an error message and leaves the TitleWindow container visible.

Another type of application might use a dashboard layout, where you have multiple panels open on the dashboard. Submitting the form could cause another area of the dashboard to update with results, while a failure could display an error message.

For more information on the TabNavigator, Accordion, and TitleWindow containers, see MX navigator containers.