NumberValidator class
The NumberValidator class ensures that a String represents a valid number. It can ensure that the input falls: - within a given range (specified by minValue and maxValue), - is an integer (specified by domain), - is non-negative (specified by allowNegative), - does not exceed the specified precision.
The validator correctly validates formatted numbers (e.g., "12,345.67") and you can customize the thousandsSeparator and decimalSeparator properties for internationalization.
class NumberValidator extends WidgetValidator { static const String INTEGER = "integer"; static const String DOUBLE = "double"; /** * Specifies whether negative numbers are permitted. * Allowed by default. */ bool allowNegative; /** * The character used to separate the whole from the fractional part of the * number. Cannot be a digit and must be distinct from the [thousandsSeparator]. * By default equals "." */ String decimalSeparator; /** * Type of number to be validated. * Permitted values are [NumberValidator.INTEGER] and [NumberValidator.DOUBLE]. * By default equals [NumberValidator.DOUBLE]. */ String domain; /** * Maximum value for a valid number. A value of null means there is no maximum. */ num maxValue; /** * Minimum value for a valid number. A value of null means there is no minimum. */ num minValue; /** * The maximum number of digits allowed to follow the decimal point. * Can be any nonnegative integer. */ int precision; /** * The character used to separate thousands in the whole part of the number. * Cannot be a digit and must be distinct from the [decimalSeparator]. */ String thousandsSeparator; /** * Error message when the decimal separator character occurs more than once. * By default equals "The decimal separator can occur only once." */ String decimalPointCountError; /** * Error message when the value exceeds the [maxValue] property. * By default equals "The number entered is too large." */ String exceedsMaxError; /** * Error message when the number must be an integer, as defined by the * [domain] property. * By default it's equals "The number must be an integer." */ String integerError; /** * Error message when the value contains invalid characters. * * By default it equals "The input contains invalid characters." */ String invalidCharError; /** * Error message when the value contains invalid format characters, which * means that it contains a digit or minus sign (-) as a separator character, * or it contains two or more consecutive separator characters. * * By default it equals "One of the formatting parameters is invalid." */ String invalidFormatCharsError; /** * Error message when the value is less than [minValue]. * * By default it equals "The amount entered is too small." */ String lowerThanMinError; /** * Error message when the value is negative and the [allowNegative] * property is [false]. * * By default it equals "The amount may not be negative." */ String negativeError; /** * Error message when the value has a precision that exceeds the value defined * by the precision property. * * By "default" it equals "The amount entered has too many digits beyond the decimal point." */ String precisionError; /** * Error message when the thousands separator is in the wrong location. * * By default it equals "The thousands separator must be followed by three digits." */ String separationError; NumberValidator(Widget widget, { this.allowNegative:true, this.decimalPointCountError:"The decimal separator can only occur once.", this.decimalSeparator:".", this.domain:NumberValidator.DOUBLE, this.exceedsMaxError:"The number entered is too large.", this.integerError:"The number must be an integer.", this.invalidCharError:"The input contains invalid characters.", this.invalidFormatCharsError:"One of the formatting parameters is invalid.", this.lowerThanMinError:"The amount entered is too small.", this.maxValue:null, this.minValue:null, this.negativeError:"The amount may not be negative.", this.precision:-1, this.precisionError:"The amount entered has too many digits beyond the decimal point.", this.separationError:"The thousands separator must be followed by three digits.", this.thousandsSeparator:","}) : super(widget); /** * Override of the base class [doValidation()] method * to validate a number. * * <p>You do not call this method directly; * Flex calls it as part of performing a validation. * If you create a custom Validator class, you must implement this method. </p> * * @param value Object to validate. * * @return An Array of ValidationResult objects, with one ValidationResult * object for each field examined by the validator. * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ /** * Executes the validation logic of this validatorto validate a number. * Invalid result returns an List of [ValidationResult] objects, with one * ValidationResult object for each field examined by the validator that * failed validation. * * You must override this method in a subclass of a validator class. */ List<ValidationResult> doValidation(dynamic value) { List<ValidationResult> results = super.doValidation(value); // Return if there are errors // or if the required property is set to [false] and length is 0. String val = value != null? value.toString() : ""; if (results.length > 0 || ((val.length == 0) && !required)) return results; else return _validateNumber(value); } /** * Validate [value] and return List of [ValidationResult] objects, with one * ValidationResult object for each field examined by the validator. */ List<ValidationResult> _validateNumber(dynamic value) { List<ValidationResult> results = []; String input = value.toString(); int len = input.length; bool isNegative = false; int i; String c; // Make sure the formatting character parameters are unique, // are not digits or the negative sign, // and that the separators are one character. String invalidFormChars = Validator.DECIMAL_DIGITS + "-"; if (decimalSeparator == thousandsSeparator || invalidFormChars.indexOf(decimalSeparator) != -1 || invalidFormChars.indexOf(thousandsSeparator) != -1 || decimalSeparator.length != 1 || thousandsSeparator.length != 1) { results.add(new ValidationResult(true, invalidFormatCharsError)); return results; } // Check for invalid characters in input. String validChars = Validator.DECIMAL_DIGITS + "-" + decimalSeparator + thousandsSeparator; for (i = 0; i < len; i++) { c = input[i]; if (validChars.indexOf(c) == -1) { results.add(new ValidationResult(true, invalidCharError)); return results; } } // Check if the input is negative. if (input[0] == "-") { if (len == 1) { // we have only '-' char results.add(new ValidationResult(true, invalidCharError)); return results; } else if (len == 2 && input[1] == '.') { // handle "-." results.add(new ValidationResult(true, invalidCharError)); return results; } // Check if negative input is allowed. if (!allowNegative) { results.add(new ValidationResult(true, negativeError)); return results; } // Strip off the minus sign, update some variables. input = input.substring(1); len--; isNegative = true; } // Make sure there's only one decimal point. if (input.indexOf(decimalSeparator) != input.lastIndexOf(decimalSeparator)) { results.add(new ValidationResult(true, decimalPointCountError)); return results; } // Make sure every character after the decimal is a digit, // and that there aren't too many digits after the decimal point: // if domain is int there should be none, // otherwise there should be no more than specified by precision. int decimalSeparatorIndex = input.indexOf(decimalSeparator); if (decimalSeparatorIndex != -1) { int numDigitsAfterDecimal = 0; if (i == 1 && i == len) { // we only have a '.' results.add(new ValidationResult(true, invalidCharError)); return results; } for (i = decimalSeparatorIndex + 1; i < len; i++) { // This character must be a digit. if (Validator.DECIMAL_DIGITS.indexOf(input[i]) == -1) { results.add(new ValidationResult(true, invalidCharError)); return results; } ++numDigitsAfterDecimal; // There may not be any non-zero digits after the decimal // if domain is int. if (domain == NumberValidator.INTEGER && input[i] != "0") { results.add(new ValidationResult(true, integerError)); return results; } // Make sure precision is not exceeded. if (precision != -1 && numDigitsAfterDecimal > precision) { results.add(new ValidationResult(true, precisionError)); return results; } } } // Make sure the input begins with a digit or a decimal point. if (Validator.DECIMAL_DIGITS.indexOf(input[0]) == -1 && input[0] != decimalSeparator) { results.add(new ValidationResult(true, invalidCharError)); return results; } // Make sure that every character before the decimal point // is a digit or is a thousands separator. // If it's a thousands separator, // make sure it's followed by three consecutive digits. int end = decimalSeparatorIndex == -1 ? len : decimalSeparatorIndex; for (i = 1; i < end; i++) { c = input[i]; if (c == thousandsSeparator) { if (c == thousandsSeparator) { if ((end - i != 4 && input[i + 4] != thousandsSeparator) || Validator.DECIMAL_DIGITS.indexOf(input[i + 1]) == -1 || Validator.DECIMAL_DIGITS.indexOf(input[i + 2]) == -1 || Validator.DECIMAL_DIGITS.indexOf(input[i + 3]) == -1) { results.add(new ValidationResult(true, separationError)); return results; } } } else if (Validator.DECIMAL_DIGITS.indexOf(c) == -1) { results.add(new ValidationResult(true, invalidCharError)); return results; } } // Make sure the input is within the specified range. if (minValue != null || maxValue != null) { // First strip off the thousands separators. for (i = 0; i < end; i++) { if (input[i] == thousandsSeparator) { String left = input.substring(0, i); String right = input.substring(i + 1); input = left + right; } } // Translate the value back into standard english // If the decimalSeperator is not '.' we need to change it to '.' // so that the number casting will work properly if (decimalSeparator != '.') { int dIndex = input.indexOf(decimalSeparator); if (dIndex != -1) { String dLeft = input.substring(0, dIndex); String dRight = input.substring(dIndex + 1); input = dLeft + '.' + dRight; } } // Check bounds double x = double.parse(input, (String source) => 0.0); if (isNegative) x = -x; if (minValue != null && x < minValue) { results.add(new ValidationResult(true, lowerThanMinError)); return results; } if (maxValue != null && x > maxValue) { results.add(new ValidationResult(true, exceedsMaxError)); return results; } } return results; } }
Extends
Validator > WidgetValidator > NumberValidator
Static Properties
const String DOUBLE #
static const String DOUBLE = "double"
const String INTEGER #
static const String INTEGER = "integer"
Constructors
new NumberValidator(Widget widget, {bool allowNegative: true, String decimalPointCountError: "The decimal separator can only occur once.", String decimalSeparator: ".", String domain: NumberValidator.DOUBLE, String exceedsMaxError: "The number entered is too large.", String integerError: "The number must be an integer.", String invalidCharError: "The input contains invalid characters.", String invalidFormatCharsError: "One of the formatting parameters is invalid.", String lowerThanMinError: "The amount entered is too small.", num maxValue: null, num minValue: null, String negativeError: "The amount may not be negative.", int precision: -1, String precisionError: "The amount entered has too many digits beyond the decimal point.", String separationError: "The thousands separator must be followed by three digits.", String thousandsSeparator: ","}) #
Creates a new Object instance.
Object instances have no meaningful state, and are only useful through their identity. An Object instance is equal to itself only.
NumberValidator(Widget widget, { this.allowNegative:true, this.decimalPointCountError:"The decimal separator can only occur once.", this.decimalSeparator:".", this.domain:NumberValidator.DOUBLE, this.exceedsMaxError:"The number entered is too large.", this.integerError:"The number must be an integer.", this.invalidCharError:"The input contains invalid characters.", this.invalidFormatCharsError:"One of the formatting parameters is invalid.", this.lowerThanMinError:"The amount entered is too small.", this.maxValue:null, this.minValue:null, this.negativeError:"The amount may not be negative.", this.precision:-1, this.precisionError:"The amount entered has too many digits beyond the decimal point.", this.separationError:"The thousands separator must be followed by three digits.", this.thousandsSeparator:","}) : super(widget);
Properties
bool allowNegative #
Specifies whether negative numbers are permitted. Allowed by default.
bool allowNegative
String decimalPointCountError #
Error message when the decimal separator character occurs more than once. By default equals "The decimal separator can occur only once."
String decimalPointCountError
String decimalSeparator #
The character used to separate the whole from the fractional part of the number. Cannot be a digit and must be distinct from the thousandsSeparator. By default equals "."
String decimalSeparator
String domain #
Type of number to be validated. Permitted values are NumberValidator.INTEGER and NumberValidator.DOUBLE. By default equals NumberValidator.DOUBLE.
String domain
bool enabled #
Property to enable/disable validation process.
Setting this value to false will stop the validator from performing validation. When a validator is disabled, it dispatches no events, and the validate method returns ValidationEvent.VALID instance.
bool enabled = true
String exceedsMaxError #
Error message when the value exceeds the maxValue property. By default equals "The number entered is too large."
String exceedsMaxError
String integerError #
Error message when the number must be an integer, as defined by the domain property. By default it's equals "The number must be an integer."
String integerError
String invalidCharError #
Error message when the value contains invalid characters.
By default it equals "The input contains invalid characters."
String invalidCharError
String invalidFormatCharsError #
Error message when the value contains invalid format characters, which means that it contains a digit or minus sign (-) as a separator character, or it contains two or more consecutive separator characters.
By default it equals "One of the formatting parameters is invalid."
String invalidFormatCharsError
List<ValidationListener> listeners #
List of ValidationListener's
List<ValidationListener> listeners = new List<ValidationListener>()
String lowerThanMinError #
Error message when the value is less than minValue.
By default it equals "The amount entered is too small."
String lowerThanMinError
num maxValue #
Maximum value for a valid number. A value of null means there is no maximum.
num maxValue
num minValue #
Minimum value for a valid number. A value of null means there is no minimum.
num minValue
String negativeError #
Error message when the value is negative and the allowNegative
property is false
.
By default it equals "The amount may not be negative."
String negativeError
OnInvalid onInvalid #
Callback function invokes when result of validation is invalid.
OnInvalid onInvalid
OnValid onValid #
Callback function invokes when result of validation is valid.
OnValid onValid
int precision #
The maximum number of digits allowed to follow the decimal point. Can be any nonnegative integer.
int precision
String precisionError #
Error message when the value has a precision that exceeds the value defined by the precision property.
By "default" it equals "The amount entered has too many digits beyond the decimal point."
String precisionError
bool required #
If true specifies that a missing or empty value causes a validation error.
bool required = true
String requiredError #
Error message when a value is missing and the required
property is true.
By default equals "This field is required."
String requiredError = "This field is required."
String separationError #
Error message when the thousands separator is in the wrong location.
By default it equals "The thousands separator must be followed by three digits."
String separationError
String thousandsSeparator #
The character used to separate thousands in the whole part of the number. Cannot be a digit and must be distinct from the decimalSeparator.
String thousandsSeparator
Methods
List<ValidationResult> doValidation(value) #
Override of the base class doValidation()
method
to validate a number.
<p>You do not call this method directly; Flex calls it as part of performing a validation. If you create a custom Validator class, you must implement this method. </p>
@param value Object to validate.
@return An Array of ValidationResult objects, with one ValidationResult object for each field examined by the validator.
@langversion 3.0 @playerversion Flash 9 @playerversion AIR 1.1 @productversion Flex 3
Executes the validation logic of this validatorto validate a number. Invalid result returns an List of ValidationResult objects, with one ValidationResult object for each field examined by the validator that failed validation.
You must override this method in a subclass of a validator class.
List<ValidationResult> doValidation(dynamic value) { List<ValidationResult> results = super.doValidation(value); // Return if there are errors // or if the required property is set to [false] and length is 0. String val = value != null? value.toString() : ""; if (results.length > 0 || ((val.length == 0) && !required)) return results; else return _validateNumber(value); }
ValidationEvent validate(value, [bool fireEvent = true]) #
Performs validation of value and notifies the listeners of the result if fireEvent equals true.
ValidationEvent validate(dynamic value, [bool fireEvent = true]) { ValidationEvent resultEvent; if (enabled && (value != null || required)) { // Validate if the target is required or our value is non-null. resultEvent = _processValidation(value); } else { // We assume if value is null and required is false that // validation was successful. resultEvent = new ValidationEvent(ValidationEvent.VALID); } // Send notification to listeners if (fireEvent && resultEvent != null) { listeners.forEach((ValidationListener listener){ listener(resultEvent); }); } // Invoke callback validation functions if (onValid != null && resultEvent.type == ValidationEvent.VALID) { onValid(); } else if (onInvalid != null && resultEvent.type == ValidationEvent.INVALID) { onInvalid(resultEvent.results); } return resultEvent; }