Form Validation for the Lazy Programmer in Flex

Forms… Any data-centric application is going to have its fair share of them. They are fairly tedious work. Layout out the form, manage the output, validate the output, over and over. Validation is best when it is active, to let the user know that they have made a mistake before they try to submit the data. Optimally the user won’t be allowed to continue until the form data is complete and accurate.

Every form I’ve written carries the same structure for validation, so as a dedicated lazy programmer I wrote a simple FormValidator class to handle the boilerplate.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package com.visualempathy.validators
{
	import flash.display.DisplayObject;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
 
	import mx.events.ValidationResultEvent;
	import mx.validators.Validator;
 
	[Bindable]
	public class FormValidator extends EventDispatcher
	{
		public var formIsValid:Boolean = false;
 
		public var validators:Array;
		private var focusedFormControl:DisplayObject;
 
		public function FormValidator(target:IEventDispatcher=null)
		{
			super(target);
		}
 
		public function validateForm(event:Event):void
		{
			focusedFormControl = event.target as DisplayObject;
			formIsValid = true;
 
			for each( var validator:Validator in validators )
				validate(validator);
		}
 
		private function validate(validator:Validator):Boolean
		{
			var validatorSource:DisplayObject = validator.source as DisplayObject;
			var supressEvents:Boolean = validatorSource != focusedFormControl;
			var event:ValidationResultEvent = validator.validate(null, supressEvents)
			var currentControlIsValid:Boolean = event.type == ValidationResultEvent.VALID;
 
			formIsValid = formIsValid && currentControlIsValid;
			return currentControlIsValid;
		}
	}
}

in the MXML I add an Array structure to hold the Validators, and add the FormValidator like so:

1
2
3
4
5
6
7
8
9
10
	<mx:Array id="validators">
		<mx:StringValidator id="studioNameValidator" source="{this.studioNameInput}" property="text" required="true"/>
		<mx:EmailValidator id="emailValidator" source="{this.emailInput}" property="text" required="true"/>
		<mx:PhoneNumberValidator id="phoneValidator" source="{this.phoneInput}" property="text" required="true"/>
		<mx:StringValidator id="addValidator" source="{this.addressInput}" property="text" required="true"/>
		<mx:StringValidator id="cityValidator" source="{this.cityInput}" property="text" required="true"/>
		<mx:StringValidator id="stateValidator" source="{this.stateInput}" minLength="2" maxLength="2" property="text" required="true"/>
		<mx:ZipCodeValidator id="zipcodeValidator" source="{this.zipcodeInput}" property="text" required="true"/>
	</mx:Array>
	<validators:FormValidator id="formValidator" validators="{this.validators}"/>

This allows you to add an arbitrary number of validators. Then in the various inputs:

1
<mx:TextInput id="studioNameInput" text="{this.studio.name}" width="100%" change="this.formValidator.validateForm(event);"/>

with the button to commit the changes enabled only when the form is valid:

1
<mx:Button id="saveChangesBtn" label="save" click="handleSaveChanges()" enabled="{this.formValidator.formIsValid}"/>

It reduces some of the pain and tedium with the process of creating forms, which is always welcome.

  • http://rachaelandtom.info/blogs/falken Tom Chiverton

    Doesn’t FlexLib already have such a device ?

  • Joel

    Assuming you are referring to the AdvancedForm, then yes. AdvancedForm is a container and carries the baggage of extending Form. It is a great component, but many times I want to lay out a form, not a Form, and have freedom in how I use my visual space.

    Then again, maybe you are referring to something entirely different, in that case you’d need to be more specific.

  • Steve

    Hey, nice solution Joel, more elegant than mine, which was puely actionscript and flag setting/checking.

    I too seem to always be building forms and WIZARDS… your soultion works brilliantly as a mechanism of validating before the next wizard pane is shown/ next button to move to the next pane is enabled.

  • travis

    Thanks for this its way cleaner then a lot of other examples out there

  • travis

    question? I”m creating an update form. Every text input has an update button. How can I make it so I toggle each button to be enabled or disabled on verification. Thanks

  • travis

    never mind i figured it out just got rid of the array and called the FormValidator class for each text input which makes each form unique

  • Alfonso

    Hi, I’m creating a tab navigator and my form is on the second tab, when I call validate, I’m getting an error because
    var validatorSource:DisplayObject = validator.source as DisplayObject
    returns null.

    How can I fix it?

    thanks

  • http://evancharlton.com/ Evan Charlton

    I just wanted to say that this came in handy and saved me from having to write the ~100 lines to do it :-)

    Cheers!

  • http://evancharlton.com/ Evan Charlton

    I just wanted to say that this came in handy and saved me from having to write the ~100 lines to do it :-)

    Cheers!

  • http://twitter.com/sir_teddy Tadas Ruginis

    Does anybody know what happend to the validator in Flash Builder (flex 4) ??? i seem to have all sorts of errors occuring when using it with sparks.

  • http://twitter.com/sir_teddy Tadas Ruginis

    Does anybody know what happend to the validator in Flash Builder (flex 4) ??? i seem to have all sorts of errors occuring when using it with sparks.

  • https://me.yahoo.com/a/Rm6hPyhkpJG5vZKEOWItdusUNcVmSVfFq8M-#67dde Vijayakumar

    Does it compatible with various forms..?

  • https://me.yahoo.com/a/Rm6hPyhkpJG5vZKEOWItdusUNcVmSVfFq8M-#67dde Vijayakumar

    Does it compatible with various forms..?

  • http://openid-provider.appspot.com/srstclair Shane

    You are a gentleman and a scholar.

  • http://openid-provider.appspot.com/srstclair Shane

    You are a gentleman and a scholar.

  • Reggie

    This doesn't work for ComboBox form items.

  • http://joelhooks.com Joel Hooks

    Combo boxes require object validators. It does work, you just
    generally need a custom validator.

  • Reggie

    This doesn't work for ComboBox form items.

  • http://joelhooks.com Joel Hooks

    Combo boxes require object validators. It does work, you just
    generally need a custom validator.

  • Surendragurjar

    Great work…..

  • http://technohippies.wordpress.com Daniel Pyrathon

    Neat stuff!! great work

  • kwigg22

    Does this work? I keep getting prefix element is not bound for the validators:FormValidator line

  • abhi

    can this same work for flex 4 spark form items?

  • http://joelhooks.com Joel Hooks

    I haven't tried it, but conceptually it should work. I don't think validators have changed.

  • mford

    Still one of my favorites.  I use this throughout my apps.  Came across an issue, so I thought I’d share.  I have a validator that is enabled conditionally…

    This caused errors using Joel’s code.  So I modified his
    private function validate(validator:Validator):Booleanto…var currentControlIsValid:Boolean = true; if (validator.enabled == true) { //MPF var validatorSource:DisplayObject = validator.source as DisplayObject; var supressEvents:Boolean = validatorSource != focusedFormControl; var event:ValidationResultEvent = validator.validate(null, supressEvents) currentControlIsValid = event.type == ValidationResultEvent.VALID;} formIsValid = formIsValid && currentControlIsValid;return currentControlIsValid;}

  • http://www.facebook.com/people/Mike-Rosoft/100002168929748 Mike Rosoft

    i have the same problem… 

  • http://joelhooks.com Joel Hooks

    This was written for Flex 3 something. It might need some adjustment.