generic_validator 1.0.0
generic_validator: ^1.0.0 copied to clipboard
A generic validator with business logic separation in mind.
This package provides APIs to facilitate separating validation and business rules from the application presentation.
Features #
- Express your rules in a declarative way.
- Feedback doesn't have to be of a certain type (totally generic)
- Group related rules together and eliminate if else statements.
- Supports asynchronous evalution of rules.
Usage #
Check /example
for a full detailed usage. #
#
You can declare a ValidationRule
with a ruler
which encapsulates your validation and of course the negativeFeedback
of your choice which can be of any type then call apply
on it.
final myName = 'Ahmed';
final arabicName = 'احمد';
final nameRule = ValidationRule(
ruler: (value) {
if (RegExp("[A-Za-z]").hasMatch(value)) {
return true;
}
return false;
},
negativeFeedback: "Name has to be in English");
final validResult = nameRule.apply(myName); // Returns Valid
final invalidResult = nameRule.apply(arabicName); // Returns Invalid which has a reasons property of the type of the negative feedback passed earlier.
#
Grouping rules together can be convenient in that case, you can subclass the Validator
and override its rules
getter declaring your rules.
class NameValidator extends Validator<String, dynamic> {
@override
List<ValidationRule<String, dynamic>> get rules => [
ValidationRule(
ruler: (value) {
if (value.isNotEmpty){
return true;
}
return false;
},
negativeFeedback: "Name can't be empty"),
ValidationRule(
ruler: (value) {
if (RegExp("[A-Za-z]").hasMatch(value)) {
return true;
}
return false;
},
negativeFeedback: "Name has to be in English"),
];
}
Call validate
on it to get the result:
final aValidName = "Ahmed";
final invalidName = "";
final nameValidator = NameValidator();
final validResult = nameValidator.validate(aValidName); // Returns Valid
final invalidResult = nameValidator.validate(invalidName); // Returns Invalid with a reasons property
You can also mixin StringRules
which has common rules like notEmpty
class NameValidator extends Validator<String, dynamic> with StringRules {
@override
List<ValidationRule<String, dynamic>> get rules => [
notEmpty<String>(negativeFeedback: "This field can't be empty."),
max(
maxLength: 10,
negativeFeedback: "Name can't be more than 10 characters."),
ValidationRule(
ruler: (value) {
if (RegExp("[A-Za-z]").hasMatch(value)) {
return true;
}
return false;
},
negativeFeedback: "Name has to be in English"),
];
}
#
You can create both an AsyncValidationRule
and an AsyncValidator
which can have both ValidationRule
and AsyncValidationRules
rules.
#
A validation result have a couple of convient methods like when
, maybeWhen
, map
, and maybeMap
. for usages like:
// Map validation result objects to String or null for use with the TextFormfield validator function.
nameValidator.validate(val).maybeMap(
invalid: (invalid) => invalid.reasons.first,
orElse: () => null,
);
// Side effects based on a validation result.
phoneValidator.validate(val).maybeWhen(
invalid: (reasons) {
// show a dialog
},
orElse: () {
// pop the current screen
},
);