Skip to content

Validators API

PropertyValidator<T>

Base class for all property validators.

dart
abstract class PropertyValidator<T> {
  const PropertyValidator();
  Map<String, dynamic>? validate(T? value);
}

Return null if valid. Return a Map<String, dynamic> with error details if invalid. The error map should contain a 'message' key for display purposes.

PropertyValidators Factory

All built-in validators are created through PropertyValidators static methods.

required

dart
static PropertyValidator<dynamic> required({String? message})

Validates that the value is:

  • Not null
  • Not an empty String
  • Not an empty Iterable

Error key: required

Error detail:

dart
{'required': {'message': 'This field is required'}}

Note: Setting required: true on a property automatically adds this validator.

min / max

dart
static PropertyValidator<num> min(num value, {String? message})
static PropertyValidator<num> max(num value, {String? message})

Validates numeric bounds. null values are treated as valid (use required for null checks).

Error key: min / max

Error detail:

dart
{'min': {'min': 10, 'actual': 5, 'message': 'Must be at least 10'}}
{'max': {'max': 100, 'actual': 150, 'message': 'Must be at most 100'}}

minLength / maxLength

dart
static PropertyValidator<String> minLength(int length, {String? message})
static PropertyValidator<String> maxLength(int length, {String? message})

Validates string length. null values are treated as valid.

Error key: minLength / maxLength

Error detail:

dart
{'minLength': {'requiredLength': 3, 'actualLength': 1, 'message': 'Must be at least 3 characters'}}
{'maxLength': {'requiredLength': 200, 'actualLength': 250, 'message': 'Must be at most 200 characters'}}

pattern

dart
static PropertyValidator<String> pattern(String pattern, {String? message})

Validates that a string matches a regular expression. null and empty values are treated as valid.

Error key: pattern

Error detail:

dart
{'pattern': {'requiredPattern': '^[a-z]+$', 'actualValue': '123', 'message': 'Does not match the required pattern'}}

identifier

dart
static PropertyValidator<String> identifier({String? message})

Convenience for pattern(r'^[a-zA-Z_][a-zA-Z0-9_]*$'). Validates a Dart-style identifier.

Error key: pattern

Default message: 'Must be a valid identifier (letters, digits, underscores)'

email

dart
static PropertyValidator<String> email({String? message})

Validates email format using a comprehensive regex pattern.

Error key: email

Error detail:

dart
{'email': {'message': 'Must be a valid email address'}}

custom

dart
static PropertyValidator<T> custom<T>(
  Map<String, dynamic>? Function(T? value) validate,
)

Creates a validator from a function. Return null for valid, or an error map for invalid.

dart
PropertyValidators.custom<String>((value) {
  if (value != null && value.startsWith('_')) {
    return {'prefix': {'message': 'Cannot start with underscore'}};
  }
  return null;
});

Utility: toIdentifier

dart
static String toIdentifier(String? value)

Converts a human-readable string to a valid identifier:

  • Trims whitespace
  • Converts to lowercase
  • Replaces non-alphanumeric characters with underscores
  • Collapses multiple underscores
  • Strips leading/trailing underscores
InputOutput
'First Name''first_name'
'pH Meter - Type A''ph_meter_type_a'
' extra spaces ''extra_spaces'
null''

Error Format Convention

All built-in validators embed a 'message' key in their error detail:

dart
{
  'errorKey': {
    'message': 'Human-readable error message',
    // ... additional details
  }
}

The PropertyCollectionEditor and defaultValidationMessages (from reactive_forms_interop.dart) extract this message for display.

Bridging to reactive_forms

The function bridgeValidator(PropertyValidator) converts a PropertyValidator to a reactive_forms.Validator. This is package-internal and not exported from the barrel file.

Next Steps