philiprehberger_form_validator 0.2.0 copy "philiprehberger_form_validator: ^0.2.0" to clipboard
philiprehberger_form_validator: ^0.2.0 copied to clipboard

Declarative form validation with composable rules and JSON schemas

philiprehberger_form_validator #

Tests pub package Last updated

Declarative form validation with composable rules and JSON schemas

Requirements #

  • Dart >= 3.5

Installation #

Add to your pubspec.yaml:

dependencies:
  philiprehberger_form_validator: ^0.2.0

Then run:

dart pub get

Usage #

import 'package:philiprehberger_form_validator/form_validator.dart';

final schema = FormSchema({
  'name': [Rules.required(), Rules.minLength(2)],
  'email': [Rules.required(), Rules.email()],
});

final result = schema.validate({
  'name': 'Alice',
  'email': 'alice@example.com',
});

print(result.isValid); // true

Built-in Rules #

Rules.required()
Rules.email()
Rules.url()
Rules.minLength(3)
Rules.maxLength(100)
Rules.pattern(RegExp(r'^\d+$'))
Rules.numeric()
Rules.between(1, 100)
Rules.equals('password')    // cross-field comparison
Rules.oneOf(['a', 'b', 'c'])
Rules.custom((v) => v != null, message: 'Required')

JSON Schema Definition #

final schema = FormSchema.fromJson({
  'email': ['required', 'email'],
  'name': ['required', 'minLength:3', 'maxLength:100'],
  'age': ['numeric', 'between:18,120'],
});

Cross-field Validation #

final schema = FormSchema({
  'password': [Rules.required(), Rules.minLength(8)],
  'confirm': [Rules.required(), Rules.equals('password')],
});

final result = schema.validate({
  'password': 'secret123',
  'confirm': 'secret123',
});
print(result.isValid); // true

Conditional Validation #

final schema = FormSchema({
  'country': [Rules.required()],
  'state': [Rules.when((data) => data['country'] == 'US', Rules.required())],
});

final result = schema.validate({'country': 'US'});
print(result.hasError('state')); // true — required only when country is US

Combining Validators #

// All must pass
final strict = Rules.all([Rules.required(), Rules.minLength(8)]);

// Any can pass
final flexible = Rules.any([Rules.email(), Rules.url()]);

Async Validation #

final schema = FormSchema({'username': [Rules.required()]});

final result = await schema.validateAsync(
  {'username': 'taken'},
  asyncValidators: [
    MapEntry('username', AsyncFieldValidator(
      'Username already taken',
      (value) async => value != 'taken', // e.g. check server
    )),
  ],
);
print(result.isValid); // false

Inspecting Errors #

final result = schema.validate(data);

result.isValid;              // true if no errors
result.hasError('email');    // check specific field
result.errorsFor('email');   // list of error messages
result.allErrors;            // flat list of all errors
result.errorCount;           // total error count

API #

Class Description
FieldValidator Single validation rule with message and test function
Rules Static factory methods for built-in validators
FormSchema Schema defining validators per field, validates form data maps
FormSchema.fromJson() Create schema from JSON-like rule descriptor map
ValidationResult Result object with errors, field queries, and counts
CrossFieldValidator Validator that compares against another field's value
AsyncFieldValidator Async validation rule (e.g. server-side checks)
Rules.when() Conditional validator based on form data
Rules.all() Composite validator requiring all rules to pass
Rules.any() Composite validator requiring any rule to pass

Development #

dart pub get
dart analyze --fatal-infos
dart test

Support #

If you find this project useful:

Star the repo

🐛 Report issues

💡 Suggest features

❤️ Sponsor development

🌐 All Open Source Projects

💻 GitHub Profile

🔗 LinkedIn Profile

License #

MIT