I'm trying to set up an interface with validation and am trying to do
a couple of things at the same time:
* Enable/disable some buttons as a user types into a couple of input
areas. So, the button higlight is triggered on click.
* Validate each input area once the user leaves it. So, the
validation/error is triggered on the default of valueCommmit.
Using standard validators, the input areas are validated when their
value is confirmed - which is exaclty what I want. But, I also want
the buttons to enable/disable as soon as plausible inputs are
received. Unfortunately, if I test the validator on the change event,
then the field is validated and an error shows up immediately. That's
pretty annoying for the user. For example, after typing one character
into an email input the validation error pops up. Obviously, that's
unreasonably aggressive validation.
I've had a look around at a lot of validation examples but haven't
found one to match what I'm aiming for. I've built a simple working
example and posted it here:
http://www.wombatcountry.com/flex/validator/ValidatorTest.html
View source option turned on and I'll paste the source MXML at the end
of this post. (I jammed everything into a single document for this
example.) Briefly, I'm trying to
* Provide a validation error/tip/hint when the user _leaves_ the email
input or the password input.
* Update the enabled status of the "Email my password" and "Login"
buttons after each keystroke.
This is working in the demo, but I'm pretty sure I've done it in a way
that's far more complicated than it shold be. How it works (as the
source shows):
* Copy the text of the inputs into shadow variables (public vars
declared near the top) using <binding> tags.
* Defined redundant validators that test the shadow variables instead
of the real values to avoid the validation error appearing on click.
* Put a method onto the change event for the inputs. This method
(validateOnChange) calls the shadow validators and sets a pair of
bindable flag variables (emailIsValid and lookupIsValid).
* Bind the enabled property on the buttons to the flag variables.
I actually will need something exactly like this for a form much like
this, so it's not just a made-up example. However:
* I'm going to need something similar with a couple of dozen inputs. I
don't want dozens of shadow variables and bunches of redundant
validators.
* There just has to be a simpler way....it's kind of unreasonably
complicated the way I've done it.
I've hunted around for an example that works like mine and failed to
find one...I've sort of pieced what I've done together bit by bit. The
behavior is right but the implementation seems far from ideal.
Can anyone suggest improvements or point me towards some feature or
behavior I've missed?
Apologies for the lengthy question and thanks in advance for answers,
suggestions, or links.
The full source is below:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute"
backgroundColor="#FFFFFF"
viewSourceURL="srcview/index.html">
<mx:Script>
<![CDATA[
import mx.events.ValidationResultEvent;
[Bindable] private var emailIsValid:Boolean =
false;
[Bindable] private var lookupIsValid:Boolean =
false;
public var
emailToValidate:String = new String();
public var
passwordToValidate:String = new String();
private function validateOnChange () : void {
// The 'lookup' and 'send password' button
enabled properties are
bound to these variables:
var
_emailValidationResult:ValidationResultEvent =
onChangeEmailValidator.validate();
emailIsValid = _emailValidationResult.type ==
ValidationResultEvent.VALID;
lookupIsValid = false;
if (emailIsValid) {
// The lookup button should be enabled
once (and only when) there
is a valid-looking
// email address and a password that
seems okay.
var
_passwordValidationResult:ValidationResultEvent =
onChangePasswordValidator.validate();
if (_passwordValidationResult.type ==
ValidationResultEvent.VALID)
lookupIsValid = true;
}
}
]]>
</mx:Script>
<mx:Binding source="{lookupEmail.text}" destination="emailToValidate"/>
<mx:Binding source="{lookupPassword.text}"
destination="passwordToValidate"/>
<mx:EmailValidator
id="onChangeEmailValidator"
source="{this}"
property="emailToValidate"
/>
<mx:StringValidator
id="onChangePasswordValidator"
source="{this}"
property="passwordToValidate"
minLength="6"
/>
<mx:EmailValidator
id="lookupEmailValidator"
source="{lookupEmail}" property="text"
required="true"
requiredFieldError="You must provide the email you registered
with previously"
/>
<mx:StringValidator
id="lookupPasswordValidator"
source="{lookupPassword}" property="text"
required="true"
requiredFieldError="You must provide your password to load
your registration"
minLength="6"
/>
<mx:Canvas>
<mx:Label x="48" y="75" text="Email Address"/>
<mx:TextInput x="48" y="48"
id="lookupEmail"
maxChars="40"
width="234"
change="validateOnChange()"
/>
<mx:Label x="290" y="75" text="Password"/>
<mx:TextInput
id="lookupPassword"
x="290" y="48"
maxChars="40" width="150"
displayAsPassword="{!showPassword.selected}"
restrict="23456789aAbBcCdDeEfFgGhHiIjJkKmMnNPqQrRsStTuUvVwWxXyYzZ!#$%^*"
change="validateOnChange()"
/>
<mx:CheckBox x="384" y="73" label="Show" id="showPassword"/>
<mx:Button
id="emailPasswordButton"
label="Email My Password"
x="48" y="102"
enabled="{emailIsValid}"
/>
<mx:Button
id="lookupButton"
label="Find My Registration"
x="290" y="102"
enabled="{lookupIsValid}"
/>
</mx:Canvas>
</mx:Application>