Reputation: 19823
I want to use a validator to ensure 2 password fields match in Flex. I want the validator to highlight form fields like a normal flex validation control. Thanks.
Upvotes: 3
Views: 15127
Reputation: 8324
I expanded on Daniel's solution, adding the ability to trigger off of the matched source as well.
import flash.events.Event;
import mx.validators.ValidationResult;
import mx.validators.Validator;
public class MatchValidator extends Validator
{
private var _matchSource: Object = null;
private var _matchProperty: String = null;
private var _noMatchError: String = "Fields did not match";
[Inspectable(category="General", defaultValue="Fields did not match")]
public function set noMatchError( argError:String):void{
_noMatchError = argError;
}
public function get noMatchError():String{
return _noMatchError;
}
[Inspectable(category="General", defaultValue="null")]
public function set matchSource( argObject:Object):void{
removeTriggerHandler();
_matchSource = argObject;
addTriggerHandler();
}
public function get matchSource():Object{
return _matchSource;
}
[Inspectable(category="General", defaultValue="null")]
public function set matchProperty( argProperty:String):void{
_matchProperty = argProperty;
}
public function get matchProperty():String{
return _matchProperty;
}
override protected function doValidation(value:Object):Array {
// Call base class doValidation().
var results:Array = super.doValidation(value.ours);
var val:String = value.ours ? String(value.ours) : "";
if (results.length > 0 || ((val.length == 0) && !required)){
return results;
}else{
if(val != value.toMatch){
results.length = 0;
results.push( new ValidationResult(true,null,"mismatch",_noMatchError));
return results;
}else{
return results;
}
}
}
override protected function getValueFromSource():Object {
var value:Object = {};
value.ours = super.getValueFromSource();
if (_matchSource && _matchProperty){
value.toMatch = _matchSource[_matchProperty];
}else{
value.toMatch = null;
}
return value;
}
override public function set triggerEvent(value:String):void
{
removeTriggerHandler();
super.triggerEvent = value;
addTriggerHandler();
}
private function addTriggerHandler():void
{
if (_matchSource)
_matchSource.addEventListener(triggerEvent,triggerHandler);
}
private function removeTriggerHandler():void
{
if (_matchSource)
_matchSource.removeEventListener(triggerEvent,triggerHandler);
}
private function triggerHandler(event:Event):void
{
validate();
}
}
Upvotes: 1
Reputation: 31
Here's a better custom validator that's more universal, clean, and works well with the 'required' field.
import mx.validators.ValidationResult;
import mx.validators.Validator;
public class MatchValidator extends Validator{
private var _matchSource: Object = null;
private var _matchProperty: String = null;
private var _noMatchError: String = "Fields did not match";
[Inspectable(category="General", defaultValue="Fields did not match")]
public function set noMatchError( argError:String):void{
_noMatchError = argError;
}
public function get noMatchError():String{
return _noMatchError;
}
[Inspectable(category="General", defaultValue="null")]
public function set matchSource( argObject:Object):void{
_matchSource = argObject;
}
public function get matchSource():Object{
return _matchSource;
}
[Inspectable(category="General", defaultValue="null")]
public function set matchProperty( argProperty:String):void{
_matchProperty = argProperty;
}
public function get matchProperty():String{
return _matchProperty;
}
override protected function doValidation(value:Object):Array {
// Call base class doValidation().
var results:Array = super.doValidation(value.ours);
var val:String = value.ours ? String(value.ours) : "";
if (results.length > 0 || ((val.length == 0) && !required)){
return results;
}else{
if(val != value.toMatch){
results.length = 0;
results.push( new ValidationResult(true,null,"mismatch",_noMatchError));
return results;
}else{
return results;
}
}
}
override protected function getValueFromSource():Object {
var value:Object = {};
value.ours = super.getValueFromSource();
if (_matchSource && _matchProperty){
value.toMatch = _matchSource[_matchProperty];
}else{
value.toMatch = null;
}
return value;
}
}
Here's an example:
<components:MatchValidator source="{passwordCheckField}" property="text" matchSource="{passwordField}" matchProperty="text"
valid="passwordsMatch = true" invalid="passwordsMatch = false" noMatchError="Passwords do not match"/>
Upvotes: 3
Reputation: 29300
I've done this in a different way using custom validation rules.
Check it out: http://martypitt.wordpress.com/2009/08/26/rule-based-asynchronous-validation-in-flex-forms/
It shows how to do async validation (eg., checking a username is available on the server), and other validation scenario's that don't fit neatly into flex's out-of-the-box framework, including two passwords match.
Eg:
<mx:Button label="Register" enabled="{ validationRules.isValid }" />
<validation:ValidationRuleCollection id="validationRules">
<validation:UsernameIsUniqueValidationRule username="{ txtUsername.text }" targetComponent="{ txtUsername }" />
<validation:EmailIsUniqueValidationRule email="{ txtEmailAddress.text }" targetComponent="{ txtEmailAddress }" />
<validation:PasswordsMustMatchValidationRule password1="{ txtPassword.text }" password2="{ txtPasswordConfirm.text }" targetComponent="{ txtPasswordConfirm }" />
<mx:StringValidator required="true" source="{ txtUsername }" property="text" requiredFieldError="{ ResourceManager.getInstance().getString( ResourceBundles.ERROR_MESSAGES , 'REQUIRED_FIELD_ERROR' )}" />
</validation:ValidationRuleCollection>
Upvotes: 2
Reputation:
enter code here
I created my own custom validator (mostly copied from date validator):
package validators
{
import mx.validators.ValidationResult;
import mx.validators.Validator;
public class PasswordValidator extends Validator
{
// Define Array for the return value of doValidation().
private var results:Array;
public function PasswordValidator()
{
super();
}
public var confirmationSource: Object;
public var confirmationProperty: String;
// Define the doValidation() method.
override protected function doValidation(value:Object):Array {
// Call base class doValidation().
var results:Array = super.doValidation(value.password);
if (value.password != value.confirmation) {
results.push(new ValidationResult(true, null, "Mismatch",
"Password Dosen't match Retype!"));
}
return results;
}
/**
* @private
* Grabs the data for the confirmation password from its different sources
* if its there and bundles it to be processed by the doValidation routine.
*/
override protected function getValueFromSource():Object
{
var value:Object = {};
value.password = super.getValueFromSource();
if (confirmationSource && confirmationProperty)
{
value.confirmation = confirmationSource[confirmationProperty];
}
return value;
}
}
}
the example mxml for using:
<validators:PasswordValidator id="pwvPasswords" required="true" source="{txtPassword}" property="text" confirmationSource="{txtPasswordConfirm}" confirmationProperty="text" trigger="{btnStep2Finish}" />
It's pretty basic, but it's mostly what I need. It only highlights the password box though, would like to get it to highlight both.
Upvotes: 6
Reputation: 23823
Unless you have to use a validator, you can simply attach a change event handler and set errorString
property of the password field when the passwords don't match. It gives the same highlighting as done by validator.
Upvotes: 0