Accessibility

Flex Quick Starts: Handling data

Table of contents


Validating data

The data that a user enters in a user interface control might or might not be appropriate for the application. In Adobe Flex applications, you use a validator to ensure the values in the fields of a form meet certain criteria. For example, you can use a validator to ensure that a user enters a valid phone number value, to ensure that a String value is longer than a set minimum length, or ensure that a ZIP code field contains the correct number of digits.

In typical client-server environments, data validation occurs on the server after data is submitted to it from the client. One advantage of using Flex validators is that they execute on the client, which lets you validate input data before transmitting it to the server. By using Flex validators, you eliminate the need to transmit data to and receive error messages back from the server, which improves the overall responsiveness of your application.

Note: Flex validators do not eliminate the need to perform data validation on the server, but provide a mechanism for improving performance by performing some data validation on the client.

Flex includes a set of validators for common types of user input data, such as ZIP codes, phone numbers, and credit card numbers.

You create validators in MXML by using a validator tag such as <mx:EmailValidator> or <mx:PhoneNumberValidator>. Validators use the following two properties to specify the item to validate:

You can set these properties in any of the following ways:

Although any client-side validation is better than none, simply adding validators to your form and using their default behavior does not provide the most usable experience for your users. The Best practices for client-side validation demonstrates how to use validators to create a usable experience for your users.

Creating a simple validator in MXML

You declare a validator in MXML using the <mx:Validator> tag or the tag for the appropriate validator type. For example, to declare the standard PhoneNumberValidator validator, you use the <mx:PhoneNumberValidator> tag.

The default behavior of Flex validators is to listen for the valueCommit event on components. In Flex, you call the event that causes a validator to run a trigger.

Note: Using the default trigger for validators results in the behavior described in the Best practices for client-side validation section — the user receives validation feedback only after they leave a control. To give immediate feedback, you can manually trigger validation in response to the change event instead of the valueCommit event. The Best practices for client-side validation section shows you how to do this.

Example

<?xml version="1.0" encoding="utf-8"?>
<mx:Application 
    xmlns:mx="http://www.adobe.com/2006/mxml" 
     viewSourceURL="src/ValidationSimpleMXML/index.html"
     width="500" height="200"
    >
    <!-- 
        Validators 
    -->
    <!-- Name must be longer than 2 characters long -->
    <mx:StringValidator 
        id="nameValidator"
        source="{nameInput}" 
        property="text"
        minLength="2"
    />
    
    <!-- Validate phone number -->
    <mx:PhoneNumberValidator 
        id="phoneValidator"
        source="{phoneInput}" property="text"
    />
    
    <!-- Validate email -->
    <mx:EmailValidator
        id="emailValidator"
        source="{emailInput}" property="text"
    />

    <!-- 
        User interface 
    -->
    <mx:Panel title="Phone number validator">        
        <mx:Form>
            <mx:FormItem label="Name:">
                <mx:TextInput 
                    id="nameInput"
                />
            </mx:FormItem>
            <mx:FormItem label="Phone: ">
                <mx:TextInput 
                    id="phoneInput"
                />
            </mx:FormItem>
            <mx:FormItem label="Email: ">
                <mx:TextInput 
                    id="emailInput"
                />
            </mx:FormItem>
        </mx:Form>
    </mx:Panel>
</mx:Application>

Result

AlertThis content requires Flash

Download the free Flash Player now!

Get Adobe Flash Player

To view the full source, right-click the Flex application and select View Source from the context menu.

Creating a simple validator in ActionScript

You declare validators in ActionScript either in a script block within an MXML file, or in an ActionScript file, as the following example shows.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application 
    xmlns:mx="http://www.adobe.com/2006/mxml" 
    viewSourceURL="src/ValidationSimpleActionScript/index.html"
    width="500" height="200"
    creationComplete="creationCompleteHandler();"
>
    <mx:Script>
        <![CDATA[
            import mx.validators.StringValidator;
            import mx.validators.PhoneNumberValidator;
            import mx.validators.EmailValidator;
            private var nameValidator:StringValidator;
            private var phoneValidator:PhoneNumberValidator;
            private var emailValidator:EmailValidator;
            private function creationCompleteHandler():void
            {
                //
                // Create validators
                //                
                // Name validator 
                //(string must be two characters or longer)
                nameValidator = new StringValidator();
                nameValidator.source = nameInput;
                nameValidator.property = "text";
                nameValidator.minLength = 2;
                // Phone validator
                phoneValidator = new PhoneNumberValidator();
                phoneValidator.source = phoneInput;
                phoneValidator.property = "text";
                // Email validator
                emailValidator = new EmailValidator();    
                emailValidator.source = emailInput;
                emailValidator.property = "text";            
            }
        ]]>
    </mx:Script>
    <!-- 
        User interface 
    -->
    <mx:Panel title="Phone number validator">        
        <mx:Form>
            <mx:FormItem label="Name:">
                <mx:TextInput 
                    id="nameInput"
                />
            </mx:FormItem>
            <mx:FormItem label="Phone: ">
                <mx:TextInput 
                    id="phoneInput"
                />
            </mx:FormItem>
            <mx:FormItem label="Email: ">
                <mx:TextInput 
                    id="emailInput"
                />
            </mx:FormItem>
        </mx:Form>
    </mx:Panel>
</mx:Application>

Result

AlertThis content requires Flash

Download the free Flash Player now!

Get Adobe Flash Player

To view the full source, right-click the Flex application and select View Source from the context menu.

Best practices for client-side validation

Flex provides you with several methods for validating data. This Quick Start describes a method of validating data that provides the most usable experience for your users.

A usable validation method must adhere, as a minimum, to the following user interface design principles for rich Internet applications.

1. Prevent, Don't Scold

The user should not be allowed to submit a form that has validation errors. The Prevent, Don't Scold principle states that whenever you can accurately prevent users from making an error you should do so, rather than allowing them to make the error and scolding them about it afterward.

A blatant violation of this principle when doing client-side validation is to validate the user's input after the user has submitted a form. In a Flex application, you can create this behavior by triggering validators in response to the click event of your form's submit button.

2. Give Immediate Feedback

The user should get immediate feedback as they are interacting with a control. Users should receive positive feedback when the value of a control becomes valid, and they should receive negative feedback when its value becomes invalid. Giving the user feedback after they leave a control also violates the Prevent, Don't Scold principle.

When a control does not give the user immediate feedback, the user only finds out about the mistake after moving off the control. To correct the mistake, the user has to return to the control, thereby expending more effort. (This example also violates another, related principle, Respect User Effort.) Even more importantly, when a user is editing the value in a field that has a validation error on it, the user doesn't know whether the changes have made the control's value valid. The user has to move off the control to find out, and then return to it to change it again if it still isn't valid.

The default behavior of Flex validators is to listen for the valueCommit event on components. This results in the behavior described previously, where the user receives validation feedback only after the user leaves a control. To give immediate feedback, you must manually trigger validation in response to the change event instead of the valueCommit event.

The examples in the Creating a simple validator in MXML and Creating a simple validator in ActionScript sections demonstrate the user experience when immediate feedback is not given.

3. Let the User Work

Although giving immediate feedback is a good thing, your application should do so in a manner that doesn't interrupt the user's flow. Subtle hints that do not interrupt the user are usually best; you should use modal dialogs, which completely interrupt the user's flow, only when absolutely necessary.

4. Innocent Until Proven Guilty

The user should be warned about a validation error on a control only if they have had a chance to interact with that control. (In other words, you should not perform validation on controls that are in their initial state and initially display a form full of validation errors.) Similarly, resetting a form should remove all validation errors.

Link: For more information on user interface design for web applications, see Aral Balkan's article on User Interface Design Principles for Web Applications.

An example of usable client-side validation

The following example demonstrates best practices in creating validation in Flex 3. It adheres to the four user interface design principles outlined above. The user is Innocent Until Proven Guilty and no validation errors are initially shown on the form. when the form is cleared. The user is immediately reassured when a control's value becomes valid (Give Immediate Feedback) and is prevented from submitting an invalid form (Prevent, Don't Scold.) Validation errors are displayed as subtle clues and help lead the user in the right direction while staying out of her way to Let The User Work.

Example

<?xml version="1.0" encoding="utf-8"?>
<mx:Application 
    xmlns:mx="http://www.adobe.com/2006/mxml" 
    viewSourceURL="src/ValidationUsable/index.html"
    width="500" height="250" 
    defaultButton="{submitButton}"
    creationComplete="creationCompleteHandler();"
>
    <mx:Script>
        <![CDATA[
            import mx.validators.Validator;
            import mx.events.ValidationResultEvent;
            import mx.controls.Alert;
  
            []
            public var formIsValid:Boolean = false;

            []
            public var formIsEmpty:Boolean = true;
    
            // Holds a reference to the currently focussed 
            // control on the form.
            private var focussedFormControl:DisplayObject;
                                  
            // Validate the form
            private function validateForm(event:Event):void 
            {                    
                // Save a reference to the currently focussed form control
                // so that the isValid() helper method can notify only
                // the currently focussed form control and not affect
                // any of the other form controls.
                focussedFormControl = event.target as DisplayObject;    

                // Mark the form as valid to start with                
                formIsValid = true;            

                // Check if form is empty
                formIsEmpty = (nameInput.text == "" && emailInput.text == ""
                    && phoneInput.text == ""); 

                // Run each validator in turn, using the isValid() 
                // helper method and update the value of formIsValid
                // accordingly.
                validate(nameValidator);                
                validate(phoneValidator);
                validate(emailValidator);
            }
     
             // Helper method. Performs validation on a passed Validator instance.
             // Validator is the base class of all Flex validation classes so 
             // you can pass any validation class to this method.  
             private function validate(validator:Validator):Boolean
             {                
                // Get a reference to the component that is the
                // source of the validator.
                 var validatorSource:DisplayObject = validator.source as DisplayObject;
                
                // Suppress events if the current control being validated is not
                // the currently focussed control on the form. This stops the user
                // from receiving visual validation cues on other form controls.
                var suppressEvents:Boolean = (validatorSource != focussedFormControl);
                
                // Carry out validation. Returns a ValidationResultEvent.
                // Passing null for the first parameter makes the validator 
                // use the property defined in the property tag of the
                // <mx:Validator> tag.
                var event:ValidationResultEvent = validator.validate(null, suppressEvents); 
                                
                // Check if validation passed and return a boolean value accordingly.
                 var currentControlIsValid:Boolean = (event.type == ValidationResultEvent.VALID);
                 
                 // Update the formIsValid flag
                 formIsValid = formIsValid && currentControlIsValid;
                 
                 return currentControlIsValid;
              }
              
              // Event handler: Gets called when all child components
              // have been created.
              private function creationCompleteHandler():void
              {
                // Set the focus on the first field so 
                // user does not have to mouse over to it.
                // Note that the user still has to click on the 
                // Flex application to give it focus. This is 
                // a currently limitation in Flex.
                  resetFocus(); 
              }
            
            // Submit form if everything is valid. 
            private function submitForm():void 
            {
                Alert.show("Form Submitted!"); 
            }
            
            // Clear the form and reset validation.
            private function clearFormHandler():void
            {
                // Clear all input fields.
                nameInput.text = "";
                phoneInput.text = "";
                emailInput.text = "";
                
                // Clear validation error messages.
                nameInput.errorString = "";
                phoneInput.errorString = "";
                emailInput.errorString = "";
                
                // Flag that the form is now clear
                formIsEmpty = true;
                
                // Set the focus on the first field so 
                // user does not have to mouse over to it.
                resetFocus();               
            }
            
            // Helper method. Sets the focus on the first field so 
            // user does not have to mouse over to it.
            private function resetFocus():void
            {
                focusManager.setFocus(nameInput);
            }
        ]]>
    </mx:Script>

    <!-- 
        Validators 
    -->
    
    <!-- Name must be longer than 2 characters long -->
    <mx:StringValidator 
        id="nameValidator"
        source="{nameInput}" 
        property="text"
        minLength="2"
    />
    
    <!-- Validate phone number -->
    <mx:PhoneNumberValidator 
        id="phoneValidator"
        source="{phoneInput}" property="text"
    />
    
    <!-- Validate email -->
    <mx:EmailValidator
        id="emailValidator"
        source="{emailInput}" property="text"
    />

    <!-- 
        User interface 
    -->
    <mx:Panel title="Phone number validator">        
        <mx:Form>
            <mx:FormItem label="Name:">
                <mx:TextInput 
                    id="nameInput"
                    change="validateForm(event);"
                />
            </mx:FormItem>
            <mx:FormItem label="Phone: ">
                <mx:TextInput 
                    id="phoneInput"
                    change="validateForm(event);"
                />
            </mx:FormItem>
            <mx:FormItem label="Email: ">
                <mx:TextInput 
                    id="emailInput"
                    change="validateForm(event);"
                />
            </mx:FormItem>
        </mx:Form>
        <mx:ControlBar horizontalAlign="center">
            <mx:Button 
                id="submitButton"
                label="Submit" 
                enabled="{formIsValid}"
            />
            <mx:Button 
                label="Clear form" 
                enabled="{!formIsEmpty}"
                click="clearFormHandler();"
            />
        </mx:ControlBar>
    </mx:Panel>

</mx:Application>

Result

AlertThis content requires Flash

Download the free Flash Player now!

Get Adobe Flash Player

To view the full source, right-click the Flex application and select View Source from the context menu.


For more information

About the author

Aral Balkan acts and sings, leads development teams, designs user experiences, architects rich Internet applications, and runs OSFlash.org, the London Macromedia User Group, and his company, Ariaware. He loves talking design patterns and writing for books and magazines. He also authored Arp, the open-source RIA framework for the Flash platform. Aral is generally quite opinionated, animated, and passionate. He loves to smile, and can even chew gum and walk at the same time.