Validating Flex forms using the Validator classes

by Peter deHaan on August 13, 2007

Another quick post on validating a form using the StringValidator, NumberValidator, ZipCodeValidator and Validator classes. Not sure if this is the best method, but I used the NumberValidator to validate that a ComboBox has a valid selection (the selectedIndex property was equal to or greater than 0), and I used a combination of StringValidator and ZipCodeValidator to make sure that the user enters a US Zip+4 zip code.

Got some good Flex Validator tips? Leave em in the comments!

Full code after the jump.

<?xml version="1.0" encoding="utf-8"?>
<!-- http://blog.flexexamples.com/2007/08/13/validating-flex-forms-using-the-validator-classes/ -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
    layout="vertical"
    verticalAlign="middle"
    backgroundColor="white"
    creationComplete="init();">
 
    <mx:Script>
        <![CDATA[
            import mx.validators.Validator;
            import mx.events.ValidationResultEvent;
            import mx.validators.ZipCodeValidatorDomainType;
            import mx.controls.Alert;
 
            [Bindable]
            private var validatorArr:Array;
 
            private function init():void {
                validatorArr = new Array();
                validatorArr.push(shippingName_stringValidator);
                validatorArr.push(shippingAddress1_stringValidator);
                validatorArr.push(shippingCity_stringValidator);
                validatorArr.push(shippingState_numberValidator);
                validatorArr.push(shippingZipCode_zipCodeValidator);
                validatorArr.push(shippingZipCode_stringValidator);
            }
 
            private function validateForm(evt:MouseEvent):void {
                var validatorErrorArray:Array = Validator.validateAll(validatorArr);;
                var isValidForm:Boolean = validatorErrorArray.length == 0;
                if (isValidForm) {
                    Alert.show("The form is valid!", "Valid form...");
                } else {
                    var err:ValidationResultEvent;
                    var errorMessageArray:Array = [];
                    for each (err in validatorErrorArray) {
                        var errField:String = FormItem(err.currentTarget.source.parent).label
                        errorMessageArray.push(errField + ": " + err.message);
                    }
                    Alert.show(errorMessageArray.join("\n\n"), "Invalid form...", Alert.OK);
                }
            }
 
            private function resetForm(evt:MouseEvent):void {
                shippingName.text = "";
                shippingAddress1.text = "";
                shippingAddress2.text = "";
                shippingCity.text = "";
                shippingState.selectedIndex = -1;
                shippingZipCode.text = "";
            }
        ]]>
    </mx:Script>
 
    <mx:XMLList id="statesXMLList">
        <state label="California" data="CA" />
        <state label="Oregon" data="OR" />
    </mx:XMLList>
 
    <mx:StringValidator id="shippingName_stringValidator"
        source="{shippingName}"
        property="text"
        minLength="2" />
 
    <mx:StringValidator id="shippingAddress1_stringValidator"
        source="{shippingAddress1}"
        property="text"
        minLength="2" />
 
    <mx:StringValidator id="shippingCity_stringValidator"
        source="{shippingCity}"
        property="text"
        minLength="2" />
 
    <mx:NumberValidator id="shippingState_numberValidator"
        source="{shippingState}"
        lowerThanMinError="This field is required."
        property="selectedIndex"
        minValue="0" />
 
    <mx:ZipCodeValidator id="shippingZipCode_zipCodeValidator"
        source="{shippingZipCode}"
        property="text"
        requiredFieldError="Please enter a zip code in ZIP+4 format."
        domain="{ZipCodeValidatorDomainType.US_ONLY}"  />
 
    <mx:StringValidator id="shippingZipCode_stringValidator"
        source="{shippingZipCode}"
        property="text"
         tooShortError="Please enter a zip code in ZIP+4 format."
        minLength="10" maxLength="10" />
 
    <mx:Form>
        <mx:FormHeading label="Shipping Information" />
        <mx:FormItem required="true" label="Name">
            <mx:TextInput id="shippingName" maxChars="96" />
        </mx:FormItem>
        <mx:FormItem required="true" label="Address">
            <mx:TextInput id="shippingAddress1" maxChars="128" />
        </mx:FormItem>
        <mx:FormItem label="">
            <mx:TextInput id="shippingAddress2" maxChars="128" />
        </mx:FormItem>
        <mx:FormItem required="true" label="City">
            <mx:TextInput id="shippingCity" maxChars="128" />
        </mx:FormItem>
        <mx:FormItem required="true" label="State">
            <mx:ComboBox id="shippingState" prompt="Please select a State..." selectedIndex="-1" dataProvider="{statesXMLList}" labelField="@label" />
        </mx:FormItem>
        <mx:FormItem required="true" label="ZIP Code">
            <mx:TextInput id="shippingZipCode" maxChars="10" restrict="0-9 \-" />
        </mx:FormItem>
        <mx:FormItem>
            <mx:HBox>
                <mx:Button label="Submit" click="validateForm(event)" />
                <mx:Button label="Reset" click="resetForm(event)" />
            </mx:HBox>
        </mx:FormItem>
    </mx:Form>
 
</mx:Application>

View source is enabled in the following example.

{ 13 comments… read them below or add one }

Richard July 31, 2009 at 1:03 pm

Any one run across a International Zip Code Validator yet? or seen any blog on where to get all the information?

Reply

Lonely in Dallas August 27, 2009 at 12:25 pm

Thank you very much for your blog – I refer to it often!

Reply

CaptainCode October 29, 2009 at 12:30 pm

Any easier way to validate a checkbox, using code built right into the Flex framework, is to use a string validator. When it attemts to validate on the checkbox, the “selected” property is automatically coerced into a string format. See the code below for an example:

<mx:FormItem label="I agree to the terms of use" required="true">
<mx:CheckBox id="terms"/>
</mx:FormItem>
<mx:StringValidator source="{terms}" required="true" property="selected" maxLength="4" requiredFieldError="You must agree to the Terms of Use." tooLongError="You must agree to the Terms of Use."/>

Clean, simple, built-in, and best of all…. 4 lines of MXML.

Reply

Kethya November 11, 2009 at 2:29 am

Hi everyone,

I am try to put two validators on one control, but it doesn’t seem working well.
The logic is here.
I put requireValidator and emailValidator on a textBox.
when I click on “myButton” do validation.
- My expectation is:
if I don’t in put any thing we have required validator error raise
if I input some text but not match email pattern it will have emailValidator error raise
- My result:
if I don’t input any text requiredFieldValidator raise (correct)
if I input text but not follow email pattern the emailValidator raise but it doesn’t draw red rectangle around my text input and doesn’t show the validate message

Please anyone helps,

Thanks

Kethya

Here is my sample code:
====================================

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
	<mx:Script>
		<![CDATA[
			import mx.controls.Alert;
			import mx.validators.Validator;
			import mx.validators.EmailValidator;
			import com.vecteurplus.sfa.util.validators.RequiredFieldValidator;
			private var _vList:Array;
			private function hBoxInit():void {
				var require:RequiredFieldValidator = new RequiredFieldValidator();
				var email:EmailValidator = new EmailValidator();
 
				require.required = true;
				require.property = "text";
				require.source = myText;
 
				email.required = false;
				email.property = "text";
				email.source = myText;
 
				_vList = new Array();
				_vList.push(require);
				_vList.push(email);
			}
 
			private function myButton_clickHandler():void {
				var result:Array = Validator.validateAll(_vList);
				if (result) {
					Alert.show("there's error");
				}
			}
		]]>
	</mx:Script>
	<mx:HBox creationComplete="hBoxInit();">
		<mx:TextInput id="myText"/>
		<mx:Button id="myButton"
		label="myButton"
		click="myButton_clickHandler();">
	</mx:HBox>
</mx:Application>

Reply

Sameera Sandaruwan November 24, 2009 at 2:54 am

1. TextInput creates dynamically

textInputBox = new MyTextInput;
textInputBox.restrict = "0-9.";
textInputBox.maxChars = 24;
amountValidator = new NumberValidator();
amountValidator.source = textInputBox;
amountValidator.property = "text";
amountValidator.allowNegative = false;
amountValidator.domain = "real";
amountValidator.precision = 4;
amountValidator.required = false;
amountValidator.maxValue = 999999999999.9999;
amountValidator.trigger = textInputBox;
amountValidator.triggerEvent = Event.CHANGE;
amountValidator.addEventListener(ValidationResultEvent.VALID, amountValid);
amountValidator.addEventListener(ValidationResultEvent.INVALID, amountInvalid);
 
private function amountValid(event:ValidationResultEvent):void
{
    valid = true;
    fieldsValidated = true;
}
 
private function amountInvalid(event:ValidationResultEvent):void
{
    valid = false;
    fieldsValidated = true;
}

2. As mention in the creation, when we exceed the limit, it shows error my red color border, and the same time if you delete them by DEL key when it come to the given acceptable limit, automatically become to green soon.
3. Leave from the field and change values of another textinput(this is just a textinput, this is a form there are some more form elemets), then come back to value exceeded textfield by SHIFT+TABS and remove the additional entered numbers, when you come to green soon your value is accepted.
4.Now again enter more values and now you are in the warn zone, then leave from the field and do the few changes in other form elements.
5. Then come back to the value exceeded text filed by MOUSE CLICK, and start delete from DEL, even though you removed additional values, still fields shows that you are in warn zone.

Actual Results:
Even when remove additional numbers,still field is Red

Expected Results:
if remove additional numbers, field should come its normal status.

Picture of this issue can be viewed at http://bugs.adobe.com/jira/browse/SDK-24372

Reply

Anonymous December 9, 2009 at 7:07 am

The index for the NumberValidator is off – it doesn’t require a selection if left at 0 that should be changed to 1

Reply

Tim December 15, 2009 at 6:13 pm

Anybody who can help me?
I want to validate the password ,which the confirm password is right for the password ?

Reply

Marc de Kwant January 30, 2010 at 1:22 am

instead of using an init function to push all validators into an array, I would do this:

<mx:ArrayCollection>
   <mx:ZipCodeValidator id="shippingZipCode_zipCodeValidator"
        source="{shippingZipCode}"
        property="text"
        requiredFieldError="Please enter a zip code in ZIP+4 format."
        domain="{ZipCodeValidatorDomainType.US_ONLY}"  />
 
    <mx:StringValidator id="shippingZipCode_stringValidator"
        source="{shippingZipCode}"
        property="text"
         tooShortError="Please enter a zip code in ZIP+4 format."
        minLength="10" maxLength="10" />
</mx:ArrayCollection>

Kind regards,

Marc

Reply

Jon March 17, 2010 at 7:30 am

Why does resetting the form still leave all the inputs as invalid (i.e. red border) ? How do you reset the form completely, so someone can start from scratch?

Reply

Peter deHaan March 17, 2010 at 8:45 am

@Jon,

Try explicitly clearing the errorString properties for each control also:

private function resetForm(evt:MouseEvent):void {
    shippingName.text = "";
    shippingAddress1.text = "";
    shippingAddress2.text = "";
    shippingCity.text = "";
    shippingState.selectedIndex = -1;
    shippingZipCode.text = "";
 
    shippingName.errorString = "";
    shippingAddress1.errorString = "";
    shippingAddress2.errorString = "";
    shippingCity.errorString = "";
    shippingState.errorString = "";
    shippingZipCode.errorString = "";
}

Peter

Reply

Shankar Ganesh April 5, 2010 at 11:15 pm

Hi,
when i downloaded this source and tried. it showing following error. Error #1009: Cannot access a property or method of a null object reference.
I dont know what mistake done. pls Help.Thanks in advance.

Reply

Monte Aspevig July 15, 2010 at 12:24 pm

When using the control.errorString = “”; to reset the form, it appears the required field validation stops working. Neither submitting the form nor tabbing through the fields and leaving a required field blank will trigger the red-outline and tool-top functionality of the form field after setting its errorString property to “”.

Reply

Peter deHaan July 15, 2010 at 3:25 pm

@Monte Aspevig,

Not sure if it is exactly the same issue (or whether you’re using Flex 3.x or 4.x), but you may want to check out http://bugs.adobe.com/jira/browse/SDK-25731 and possibly download the latest Flex 3.6 nightly build from http://opensource.adobe.com/wiki/display/flexsdk/Download+Flex+3 and see if that solves the issue.

Peter

Reply

Leave a Comment

Sorry, this blog is terrible at eating HTML comments.
If you're pasting any HTML/XML/MXML code, you need to convert your < characters to &lt; and your > characters to &gt; .

Anti-Spam Protection by WP-SpamFree

Previous post:

Next post: