I've been not satisfied by Adobe example of making custom validators making model object when you need to compare 2 or more fields. For example you want to compare password fields or you want to compare several string fields not duplicating same StringValidators. I found on net lot of hacking solution but not one clean.
So after spending several hrs exploring how Validators are functioning and found that grail was "listener" parameter. Seal source param by overloading it. Create sources field to accept sources involved in validation.
By switching the listener switch source of error listening.
package components
{
import flash.events.IEventDispatcher;
import mx.core.mx_internal;
import mx.events.FlexEvent;
import mx.events.ValidationResultEvent;
import mx.validators.IValidatorListener;
import mx.validators.StringValidator;
import mx.validators.ValidationResult;
import mx.validators.Validator;
import spark.components.TextInput;
public class CompareValidator extends StringValidator
{
private var _sources:Array;
private var _actualTriggers:Array;
private var _emptyErrorMessage:String="No value to compare with ";
private var _compareErrorMessage:String="Comparation equality failed";
private var _minmaxErrorMessage:String="Length of value should be between min and max";
public function CompareValidator()
{
super();
}
public function get actualTriggers():Array
{
return _actualTriggers;
}
[Bindable]
public function set actualTriggers(value:Array):void
{
_actualTriggers = value;
}
[Bindable]
public function get compareErrorMessage():String
{
return _compareErrorMessage;
}
public function set compareErrorMessage(value:String):void
{
_compareErrorMessage = value;
}
[Bindable]
public function set sources(value:Array):void
{
removeTriggerHandler()
_sources = value;
_actualTriggers=_sources;
listener=_sources;
addTriggerHandler();
}
public function get sources():Array
{
return _sources;
}
override public function get source():Object
{
return null;
}
override public function set source(value:Object):void
{
}
/**
* @private
*/
private function addTriggerHandler():void
{
if (_actualTriggers)
for each(var trigger:IEventDispatcher in actualTriggers)
trigger.addEventListener(FlexEvent.VALUE_COMMIT, triggerHandler);
}
private function triggerHandler(e:FlexEvent):void
{
validate();
}
/**
* @private
*/
private function removeTriggerHandler():void
{
if (actualTriggers)
for each(var trigger:IEventDispatcher in actualTriggers)
trigger.removeEventListener(FlexEvent.VALUE_COMMIT, triggerHandler);
}
override public function validate(value:Object=null, suppressEvents:Boolean=false):ValidationResultEvent
{
if (required)
{
var errorResults:Array = doValidation(null);
// Validate if the target is required or our value is non-null.
return handleResults(errorResults);
}
else
{
// We assume if value is null and required is false that
// validation was successful.
var resultEvent:ValidationResultEvent =
new ValidationResultEvent(ValidationResultEvent.VALID);
if (!suppressEvents && enabled)
{
dispatchEvent(resultEvent);
}
return resultEvent;
}
}
override protected function doValidation(value:Object):Array {
// Clear results Array.
var results:Array = [];
var comparationValue:String;
var stringResults:Array;
if(_sources)
{
for(var i:int=0;i<_sources.length;i++){
comparationValue=String(_sources[i][property]);
results=super.doValidation(comparationValue);
listener=_sources[i];
if(results.length){
this.dispatchEvent(new ValidationResultEvent(ValidationResultEvent.INVALID,false,false,_sources[i].id,results));
}else if (!compareWithRest(comparationValue)){
results[results.length]=new ValidationResult(true,"","",_compareErrorMessage);
this.dispatchEvent(new ValidationResultEvent(ValidationResultEvent.INVALID,false,false,_sources[i].id,results));
}else{
this.dispatchEvent(new ValidationResultEvent(ValidationResultEvent.VALID,false,false,_sources[i].id));
}
}
}
return results;
}
private function compareWithRest(comparationValue:String):Boolean
{
var result:Boolean=true;
for(var i:int=0;i<_sources.length;i++){
if(_sources[i][property]!=comparationValue) return false;
}
return result;
}
}
}
package components
{
import mx.controls.TextInput;
import mx.events.FlexEvent;
import mx.events.ValidationResultEvent;
import mx.messaging.FlexClient;
import mx.olap.aggregators.MinAggregator;
import mx.validators.CreditCardValidator;
import mx.validators.StringValidator;
import mx.validators.ValidationResult;
import mx.validators.Validator;
public class MultiStringValidator extends StringValidator
{
private var _sources:Array;
private var _actualTriggers:Array;
public function MultiStringValidator()
{
super();
}
public function get actualTriggers():Array
{
return _actualTriggers;
}
[Bindable]
public function set actualTriggers(value:Array):void
{
_actualTriggers = value;
}
[Bindable]
public function set sources(value:Array):void
{
removeTriggerHandler()
_sources = value;
_actualTriggers=_sources;
//listener=_sources;
addTriggerHandler();
//this.subFields=["firstNameTextInput","lastNameTextInput"];
}
public function get sources():Array
{
return _sources;
}
override public function get source():Object
{
return null;
}
override public function set source(value:Object):void
{
}
/**
* @private
*/
private function addTriggerHandler():void
{
if (_actualTriggers)
for each(var trigger:IEventDispatcher in actualTriggers)
trigger.addEventListener(FlexEvent.VALUE_COMMIT, triggerHandler);
}
private function triggerHandler(e:FlexEvent):void
{
validate();
}
/**
* @private
*/
private function removeTriggerHandler():void
{
if (actualTriggers)
for each(var trigger:IEventDispatcher in actualTriggers)
trigger.removeEventListener(FlexEvent.VALUE_COMMIT, triggerHandler);
}
override public function validate(value:Object=null, suppressEvents:Boolean=false):ValidationResultEvent
{
if (required)
{
var errorResults:Array = doValidation(null);
// Validate if the target is required or our value is non-null.
return handleResults(errorResults);
}
else
{
// We assume if value is null and required is false that
// validation was successful.
var resultEvent:ValidationResultEvent =
new ValidationResultEvent(ValidationResultEvent.VALID);
if (!suppressEvents && enabled)
{
dispatchEvent(resultEvent);
}
return resultEvent;
}
}
/* override protected function get actualListeners():Array
{
if(listener && listener is Array) return listener as Array;
if(_sources)
return _sources;
return [];
}*/
override protected function doValidation(value:Object):Array {
// Clear results Array.
var results:Array = [];
var comparationValue:String;
var stringResults:Array;
if(_sources)
{
for(var i:int=0;i<_sources.length;i++){
comparationValue=String(_sources[i][property]);
stringResults=super.doValidation(comparationValue);
listener=_sources[i];
if(stringResults.length){
this.dispatchEvent(new ValidationResultEvent(ValidationResultEvent.INVALID,false,false,_sources[i].id,stringResults));
}
else{
this.dispatchEvent(new ValidationResultEvent(ValidationResultEvent.VALID,false,false,_sources[i].id));
}
results=results.concat(stringResults);
}
}
return results;
}
private function compareWithRest(comparationValue:String):Boolean
{
var result:Boolean=true;
for(var i:int=0;i<_sources.length;i++){
if(_sources[i][property]!=comparationValue) return false;
}
return result;
}
}
}
No comments:
Post a Comment