2008. 8. 13. 12:39

[Flex3] Form, FormHeading, FormItem 레이아웃 컨테이너 / Form, FormHeading, and FormItem layout containers

Reference : http://livedocs.adobe.com/flex/3/html/layouts_08.html

Form 은 웹 어플리케이션에서 사용자 정보를 수집하는 가장 일반적인 방법이다. Form 은 등록, 구매, 결제 정보와 다른 많은 데이터 수집 업무를 위해 사용된다.

About forms

Flex 는 Form 레이아웃 컨테이너와 몇 개의 From 컨테이너 내부 컴포넌트를 이용하여 폼 개발을 지원한다. Form 컨테이너는 폼의 레이아웃을 제어하고, 폼 필드를 필수나 선택으로 표시하며, 에러메시지를 처리하고, 폼 데이터를 데이터를 체크하고 검증하는 Flex 데이터 모델과 연동한다. 또, 폼의 외관을 설정하기 위한 스타일 시트를 적용할 수 있다. 

아래의 예제에서 볼 수 있듯이, 폼을 생성하기 위해 세 개의 다른 컴포넌트를 사용한다:

Form container

A. Form 컨테이너 B. FormHeading 컨트롤 C. FormItem 컨테이너

전체 참조 정보는 Adobe Flex Language Reference Form, FormHeading, and FormItem 에서 볼 수 있다.

Creating forms
폼 생성

일반적으로 아래와 같은 요소를 정의하여 폼을 생성한다:

  • Form 컨트롤
  • Form 컨트롤 내부의 FormHeading 컴포넌트
  • Form 컨트롤 내부의 FormItem 컨테이너
  • FormItem 컨테이너 내부의 Form 필드 (ComboBox, TextInput 컨트롤)

필요에 따라 HRule 컨트롤과 같은 다른 컴포넌트도 폼에 넣을 수 있다.

Creating the Form container
Form 컨테이너 생성

Form 컨테이너는 Flex 폼의 가장 상위 컨테이너다. Form 컨테이너의 가장 큰 역할은 폼 컨텐츠의 레이아웃과 크기를 조절하는 것이다. Form 컨테이너는 항상 내부 컴포넌트를 왼쪽으로 정렬하여 수직으로 배열한다. Form 컨테이너는 하나 이상의 FormHeading 과 FormItem 컨테이너를 포함한다..

<mx:Form> 태그를 사용하여 Form 컨테이너를 정의한다. MXML, 태그, ActionScript 블럭에서 전체 폼을 참조하려면 id 값을 명시하라. 

아래의 코드 예제는  About forms 의 이미지에 해당하는 폼의 Form 컨테이너 정의를 보여준다. :

<?xml version="1.0"?>
<!-- containers\layouts\FormSimple.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

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

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

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

전체 참조 정보는 Adobe Flex Language Reference 에서 볼 수 있다.

Creating a FormHeading control
FormHeading 컨트롤 생성

FormHeading 컨트롤은 FormItem 컨테이너 그룹을 위한 추가적인 레이블을 명시한다. 레이블은 폼에 있는 컨트롤들의 왼쪽에 맞춰 정렬된다. 폼에 여러 개의 컨텐트 영역을 나타내는 여러 개의 FormHeading 컨트롤이 존재할 수 있다. 폼에 수직 공간을 생성하기 위해 FormHeading 컨트롤을 label 과 함께 사용할 수 있다.

<mx:FormHeading> 태그를 사용하여 FormHeading 컨테이너를 정의한다. MXML, 다른 태그, ActionScript 블럭에서 참조할 땐 id 값을 명시해라.

아래의 코드 예제는 About forms 이미지에서 보이는 FormHeading 컨트롤을 정의하고 있다:

<?xml version="1.0"?>
<!-- containers\layouts\FormHeadingSimple.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

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

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

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

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

이 예제를 실행한 SWF 파일은 아래와 같다:

전체 참조 정보는 Adobe Flex Language Reference 에서 볼 수 있다.

Creating a FormItem container
FormItem 컨테이너 생성

FormItem 컨테이너는 아래와 같은 부분으로 구성된 폼을 나타낸다:

  • 하나의 레이블
  • 하나 이상의 내부 컨트롤, 컨테이너

레이블은 FormItem 컨테이너의 첫 번째 컴포넌트와 수직으로 정렬되어 있고, 컨테이너의 왼쪽에 위치하며, 내부적으로 오른쪽으로 정렬되어 있다.

<mx:FormItem> 태그를 FormItem 컨테이너를 정의하기 위해 사용한다. MXML, 다른 태그, ActionScript 블럭럭에서 참조하려면 id 값을 명시하라.

아래의 예에서 볼 수 있듯이 Form 일반적으로 컨테이너는 다수의 FormItem container를 가진다:

Form containers containing multiple FormItem containers

이 예에서 FirstName, LastName, Address 라는 레이블이 있는 세 개의 FormItem 컨테이너가 정의되었다. Address FormItem 컨테이너는 주소 정보를 두 줄로 입력할 수 있도록 두 개의 컨트롤을 갖고 있다. 다른 두 개의 FormItem 컨테이너는 각각 하나의 컨트롤을 갖고 있다.

전체 정보는  Adobe Flex Language ReferenceFormItem 에서 볼 수 있다.

Specifying form item direction
폼 아이템 방향 명시

컨테이너 생성시 direction 속성의 값을 vertical 이horizontal 로 명시할 수 있다:

vertical

Flex 는 FormItem 레이블의 오른쪽에 수직으로 컴포넌트를 배열한다.



horizontal

Flex 는 FormItem 레이블의 오른쪽에 컴포넌트를 수평으로 배열한다. 모든 컴포넌트가 하나의 행에 들어가지 않으면, 여러 행으로 나눠진다. 상대적으로(%) 크기를 설정하거나 충분히 크게 크기를 설정하여 모든 컴포넌트를 하나의 선으로 배열할 수 있다.



Controlling form item label style
폼 아이템 레이블 스타일 제어

labelStyleName 스타일 속성을 통해 FormItem 레이블의 스타일을 제어할 수 있다. 아래의 예제는 FormItem 레이블의 색을 어두운 파란색으로, 폰트 크기를 20 픽셀로 설정한다:

<?xml version="1.0"?>
<!-- containers\layouts\FormItemStyle.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

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

    <mx:Script>
        <![CDATA[
            private function processValues(zip:String, pn:String):void {
                // Validate and process data.
            }
        ]]>
    </mx: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>
</mx:Application>

이 예제를 실행한 SWF 파일은 아래와 같다:

Example: A simple form
예제 : 간단한 폼

아래는 예제 폼에 대한 FormItem 컨테이너 정의를 보여주고 있다:

<?xml version="1.0"?>
<!-- containers\layouts\FormComplete.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

    <mx:Script>
        <![CDATA[
            private function submitForm():void {               
                // Handle the form submission.
            }
        ]]>
    </mx: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:ArrayCollection>
                 <mx:String>MA</mx:String>
                 <mx:String>NH</mx:String>
                 <mx:String>RI</mx:String>
              </mx:ArrayCollection>                    
            </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:ArrayCollection>
                 <mx:String>USA</mx:String>
                 <mx:String>UAE</mx:String>
                 <mx:String>UAW</mx:String>
              </mx:ArrayCollection>                    
            </mx:ComboBox>
        </mx:FormItem>

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

이 예제의 SWF 실행 파일은 아래와 같다:


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 -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

    <mx: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();
            }   
        ]]>
    </mx: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>
</mx: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 -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

    <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>
</mx: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 -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

    <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>
</mx: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. For one example of using validators with forms, see Using a Flex data model to store form 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 -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

    <mx:Script>
        <![CDATA[
            private function processValues(zip:String, pn:String):void {
                // Validate and process data.
            }
        ]]>
    </mx: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>
</mx: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 -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

    <mx: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.
            }
        ]]>
    </mx: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>
</mx: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 -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

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

    <mx:ZipCodeValidator id="zcVal"
        source="{zipCode}" property="text" 
        domain="US or Canada"/>

    <mx:PhoneNumberValidator id="pnVal" 
        source="{phoneNumber}" property="text"/>
        
    <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>
</mx: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 -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

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

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

    <!-- 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>
</mx:Application>

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

You use the <mx: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 Using a Flex data model to store form data 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 -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

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

    <!-- Define data model. -->
    <mx:Model id="myFormModel">
        <info>
            <zipCodeModel>{zipCode.text}</zipCodeModel>
            <phoneNumberModel>{phoneNumber.text}</phoneNumberModel>
        </info>
    </mx: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"/>

    <!-- 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>
</mx: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 -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

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

    <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>
</mx: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 -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

    <!-- 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>

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

    <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: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 with Flex.

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 load 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 -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

    <!-- 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>

    <mx: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);
            }
        ]]>
    </mx:Script>

    <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>
</mx: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 Using Navigator Containers.