Defining validation
Validation is defined through part methods on ValidatorFactory such as notNull()
, satisfy()
and other parts.
Each validation rule defines
- value validation, e.g
notNull()
defines that value can not be null.satisfy()
defines a predicate which has to be true to be valid etc. - devMessage - a message which will be displayed if no translation is provided.
- key - Validation error's identification. Usable for translation.
- severity - Severity of validation. By default it is
ValidationSeverity.error
.
This example defines validation that int
value can not be null and has to be greater or equal to 18.
ageInput = GladeIntInput(
validator: (v) => (v
..notNull()
..satisfy(
(value) => value >= 18,
devMessage: (_, __) => 'Value must be greater or equal to 18',
key: _ErrorKeys.ageRestriction,
))
.build(),
value: 0,
);
The order of each validation part matters. By default, the first failing part with severity error
stops validation. You can control this behavior using the following options on .build()
:
stopOnFirstError
(default:true
): Stops validation on the first error. Set tofalse
to validate all parts, collecting all errors and warnings.stopOnFirstErrorOrWarning
(default:false
): If set totrue
, validation stops on the first error or warning encountered.
Example:
ageInput = GladeIntInput(
validator: (v) => (v
..notNull(
devMessage: (_, __) => 'Value is required',
severity: ValidationSeverity.error,
)
..satisfy(
(value) => value >= 18,
devMessage: (_, __) => 'Recommended age is 18 or above',
severity: ValidationSeverity.warning,
))
.build(stopOnFirstError: false, stopOnFirstErrorOrWarning: false),
value: 0,
);
In this example, all validation parts are checked, and both errors and warnings are collected. Adjust these options to fit your validation flow.
Fields connected with textFormFieldInputValidator
will automatically call validator and validation error (if any) is passed down to fields. By default devMessage
is used unless translation is specified.
Validation severity
Each validation rule can specify a severity using the ValidationSeverity
enum. This allows you to distinguish between errors (which typically block form submission) and warnings (which inform the user but do not block submission).
The available severities are:
ValidationSeverity.error
– Indicates a validation error. This is the default and usually prevents form submission.ValidationSeverity.warning
– Indicates a warning. Warnings are shown to the user but do not block form submission.
You can set the severity for each validation part:
ageInput = GladeIntInput(
validator: (v) => (v
..notNull(
devMessage: (_, __) => 'Value is required',
severity: ValidationSeverity.error,
)
..satisfy(
(value) => value >= 18,
devMessage: (_, __) => 'Recommended age is 18 or above',
severity: ValidationSeverity.warning,
))
.build(),
value: 0,
);
In this example, if the value is null, an error is shown and form submission is blocked. If the value is less than 18, a warning is shown, but the user can still submit the form.
Skipping Specific Validation
To conditionally skip specific validations, use the shouldValidate
callback. If an input should be entirely excluded from validation, consider using conditional logic in the inputs
getter.
(v
..minLength(length: 2, shouldValidate: (_) => false)
..maxLength(length: 6))
.build();
// Omit input from validation if the condition is not met
get inputs => [if (condition) input];
This ensures that the minLength
validation is always skipped, while the maxLength
validation is applied.
If the condition is met, the input is included in the validation process.
Creating custom reusable validators
You have several options to create reusable validators.
Most straightforward way is to extend GladeValidator
(or specialised variant such as StringValidator
) and add your custom validation logic.
Creating custom part
Better way is to create a custom validation part by extending InputValidatorPart<T>
and provide that part through customPart(part)
method.
class AgeValidatorPart extends InputValidatorPart<int> {
AgeValidatorPart() : super();
@override
bool validate(int? value) {
return value != null && value >= 18;
}
}
// Usage
ageInput = GladeIntInput(
validator: (v) => (v..customPart(AgeValidatorPart())).build(),
value: 0,
);
Using validators without GladeInput
It is possible to use GladeValidator without associated GladeInput.
Just create instance of GladeValidator
(or specialised variant such as StringValidator
) and use it.
final validator = (StringValidator()..notEmpty()).build();
final result = validator.validate(null);