Validation
The Property System provides a PropertyValidator<T> abstraction for defining validation rules on property values. Validators are bridged to reactive_forms validators internally, so validation integrates with the form control lifecycle.
PropertyValidator<T>
The base class for all validators. Implement validate() to return an error map or null:
abstract class PropertyValidator<T> {
const PropertyValidator();
/// Return error map if invalid, null if valid.
Map<String, dynamic>? validate(T? value);
}Error Format
Errors are returned as a Map<String, dynamic> where:
- The key is the error type (e.g.,
'required','min','pattern') - The value is a detail map containing at minimum a
'message'key
// Example error from PropertyValidators.min(10)
{
'min': {
'min': 10,
'actual': 5,
'message': 'Must be at least 10',
}
}The PropertyCollectionEditor and reactive_forms integration extract the 'message' key for display.
PropertyValidators Factory
The PropertyValidators abstract final class provides factory methods for all built-in validators:
required
Validates that the value is not null, not an empty string, and not an empty iterable.
PropertyValidators.required()
PropertyValidators.required(message: 'Title is required')Can also be set via the required: true parameter on any property, which automatically adds this validator.
min / max
Validates numeric bounds. Works with both int and double properties.
PropertyValidators.min(1)
PropertyValidators.min(0, message: 'Must be non-negative')
PropertyValidators.max(100)
PropertyValidators.max(1000, message: 'Maximum 1000 participants')minLength / maxLength
Validates string length bounds.
PropertyValidators.minLength(3)
PropertyValidators.minLength(3, message: 'At least 3 characters required')
PropertyValidators.maxLength(200)
PropertyValidators.maxLength(200, message: 'Maximum 200 characters')pattern
Validates that a string matches a regular expression.
PropertyValidators.pattern(r'^[a-zA-Z0-9_]+$')
PropertyValidators.pattern(
r'^[a-zA-Z0-9_]+$',
message: 'Only letters, numbers, and underscores allowed',
)identifier
A convenience validator that checks for a valid Dart-style identifier (letters, digits, underscores, starting with a letter or underscore).
PropertyValidators.identifier()
PropertyValidators.identifier(message: 'Must be a valid identifier')Pattern used: ^[a-zA-Z_][a-zA-Z0-9_]*$
email
Validates that a string is a valid email address.
PropertyValidators.email()
PropertyValidators.email(message: 'Please enter a valid email')custom
Creates a validator from a predicate function for one-off validation logic.
PropertyValidators.custom<String>((value) {
if (value != null && value.contains('admin')) {
return {'forbidden': {'message': 'Cannot contain "admin"'}};
}
return null;
})Using Validators
On Property Construction
Validators are passed via the validators parameter:
StringProperty(
key: 'email',
label: 'Email',
required: true, // adds required validator automatically
validators: [
PropertyValidators.email(),
PropertyValidators.maxLength(255),
],
);Via the Builder
b.string('email', 'Email',
required: true,
validators: [
PropertyValidators.email(),
PropertyValidators.maxLength(255),
],
);Checking Validation State
// Single property
final property = StringProperty(key: 'name', label: 'Name', required: true);
property.control.valid; // false (empty string, required)
property.control.hasErrors; // true
property.control.errors; // {'required': {'message': 'This field is required'}}
// Entire collection
final errors = collection.validateAll(); // Map<String, String>
final isValid = collection.isValid; // bool
final messages = collection.validationErrors; // List<String>Touch and Error Display
Validators only show errors after the control has been "touched". Call markAsTouched() to trigger error display:
property.control.markAsTouched();
// validateAll() automatically marks all controls as touched
collection.validateAll();Validator Summary
| Validator | Type T | Error Key | Description |
|---|---|---|---|
required() | dynamic | required | Not null, not empty |
min(value) | num | min | Minimum numeric value |
max(value) | num | max | Maximum numeric value |
minLength(length) | String | minLength | Minimum string length |
maxLength(length) | String | maxLength | Maximum string length |
pattern(regex) | String | pattern | Regex match |
identifier() | String | pattern | Valid identifier format |
email() | String | email | Valid email format |
custom(fn) | T | (user-defined) | Custom function |
Utility: toIdentifier
PropertyValidators.toIdentifier() is a static utility that converts a human-readable string to a valid identifier:
PropertyValidators.toIdentifier('First Name'); // 'first_name'
PropertyValidators.toIdentifier('pH Meter - Type A'); // 'ph_meter_type_a'
PropertyValidators.toIdentifier(' extra spaces '); // 'extra_spaces'This is useful with PropertyDerivation to auto-generate identifiers from title fields.
Next Steps
- Building Forms Guide -- Validators in a complete form
- Conditions -- Conditional visibility and enabled state
- API Reference: Validators -- Full validator API