by Adobe

adobe_logo_bio

Created

23 March 2010

 Requirements
 
User level
Required products
All Flex (Download trial)
The data that a user enters in a user interface control might or might not be appropriate for the application. In applications built with Adobe Flex, 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>, in an <fx:Declarations> block. Validators use the following two properties to specify the item to validate:
 
  • source: Specifies the object that contains the property to validate. Set this to an instance of a component or a data model. You use data binding syntax in MXML to specify the value for the source property.
  • property: A String that specifies the name of the source property that contains the value to validate. This property supports dot-delimited Strings for specifying nested properties.
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"?> <!-- ValidationSimpleMXML.mxml --> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" width="500" height="200"> <fx:Declarations> <!-- 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"/> </fx:Declarations> <!-- User interface --> <s:Panel title="Phone number validator"> <mx:Form> <mx:FormItem label="Name:"> <s:TextInput id="nameInput"/> </mx:FormItem> <mx:FormItem label="Phone: "> <s:TextInput id="phoneInput"/> </mx:FormItem> <mx:FormItem label="Email: "> <s:TextInput id="emailInput"/> </mx:FormItem> </mx:Form> </s:Panel> </s:Application>

 
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"?> <!-- ValidationSimpleActionScript.mxml --> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" width="500" height="200" creationComplete="creationCompleteHandler();"> <fx: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"; } ]]> </fx:Script> <!-- User interface --> <s:Panel title="Phone number validator"> <mx:Form> <mx:FormItem label="Name:"> <s:TextInput id="nameInput"/> </mx:FormItem> <mx:FormItem label="Phone: "> <s:TextInput id="phoneInput"/> </mx:FormItem> <mx:FormItem label="Email: "> <s:TextInput id="emailInput"/> </mx:FormItem> </mx:Form> </s:Panel> </s:Application>

 
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.
 
  • 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.
     
  • 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.
     
  • 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.
  • 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.
 
An example of usable client-side validation
The following example demonstrates best practices in creating validation in Flex. 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.
 
  • Two flags, formIsValid and formIsEmpty keep track of the current state of the form. You bind the enabled property of the Submit button to the formIsValid flag, thereby preventing the user from submitting an invalid form. Similarly, you bind the enabled property of the Clear form button to the formIsEmpty flag so that it is only enabled if the form has input in it to be cleared.
  • The focussedFormControl property holds a reference to the control that last dispatched a change event (in other words, the current control that the user is on.) The validate() helper method uses this property to only display validation error messages for the current control. This is important in preventing validation error messages being shown for controls that the user has not yet interacted with.
  • When the value of a form control changes, the validateForm() event handler method uses the validate() helper method to validate all of the form controls. The value of the formIsValid flag is set to true and the user is allowed to submit the form only if all validators are valid.
  • The resetFocus() method uses the setFocus() method of the FocusManager to place the focus on the first form item. The resetFocus() method is called when the form is first loaded and, subsequently, when the form is cleared by the user. This is to save the user the effort of clicking on the first control before typing in it.
    Note: Due to a limitation in the way that browsers currently handle Flash content, the user does have to click on the Flash application once to move focus to it on the web page that it is embedded into.
     
  • The clearFormHandler() method clears the values in the form controls and also resets the validators to a valid state.
 
Example
<?xml version="1.0" encoding="utf-8"?> <!-- ValidationUsable.mxml --> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" width="500" height="250" defaultButton="{submitButton}" creationComplete="creationCompleteHandler();"> <fx:Script> <![CDATA[ import mx.validators.Validator; import mx.events.ValidationResultEvent; import mx.controls.Alert; [Bindable] public var formIsValid:Boolean = false; [Bindable] 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); } ]]> </fx:Script> <fx:Declarations> <!-- 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"/> </fx:Declarations> <!-- User interface --> <s:Panel title="Phone number validator"> <mx:Form> <mx:FormItem label="Name:"> <s:TextInput id="nameInput" change="validateForm(event);"/> </mx:FormItem> <mx:FormItem label="Phone: "> <s:TextInput id="phoneInput" change="validateForm(event);"/> </mx:FormItem> <mx:FormItem label="Email: "> <s:TextInput id="emailInput" change="validateForm(event);"/> </mx:FormItem> </mx:Form> <s:controlBarContent> <s:Button id="submitButton" label="Submit" enabled="{formIsValid}"/> <s:Button label="Clear form" enabled="{!formIsEmpty}" click="clearFormHandler();"/> </s:controlBarContent> </s:Panel> </s:Application>

 
For more information