validate_kit 1.0.1 copy "validate_kit: ^1.0.1" to clipboard
validate_kit: ^1.0.1 copied to clipboard

A zero-dependency, fluent form validation toolkit for Dart and Flutter. Chain rules for email, password, length, range, and custom logic.

validate_kit #

pub package license Dart

A zero-dependency, fluent form validation toolkit for Dart and Flutter.

Every Flutter developer writes the same validation code over and over: emails, passwords, matching fields, numeric ranges, custom regex. validate_kit turns that repetitive, nested if soup into clean, readable chains that return the first error — or every error when you want them all.

final error = FieldValidator()
    .required('Field cannot be blank')
    .email('Enter a valid email address')
    .custom((val) =>
        val!.contains('admin') ? 'Admin emails not allowed' : null)
    .validate(controller.text);

Demo #

The example app in action:

validate_kit demo

The example/ directory contains a full registration form and a live validation playground.

Highlights #

  • Fluent chaining. Compose rules in the order they should be evaluated.
  • Zero dependencies. Pure Dart. Works in Flutter, Dart CLI, and on the server. No transitive packages to audit.
  • Short-circuits by default. The chain stops at the first failure, with an opt-in aggregate() mode to collect every error instead.
  • Sensible optional fields. Every format rule skips empty values; only required forces a value, so optional fields just work.
  • Localization-ready. Override any default message per call or globally via ValidationMessages.
  • Drop-in for TextFormField. A FieldValidator is callable and exposes an asFunction tear-off, so it plugs straight into validator:.
  • Rich results. validateAll() and validateResult() give you every error and a typed result object.
  • Handy extensions. 'a@b.com'.isValidEmail, input.isBlank, and more.
  • Fully documented and tested. Public API docs on every member and a broad unit-test suite covering null safety, boundaries, and edge cases.

Installation #

Add the dependency to your pubspec.yaml:

dependencies:
  validate_kit: ^1.0.0

Then run:

flutter pub get   # or: dart pub get

Quick start #

import 'package:validate_kit/validate_kit.dart';

final emailValidator = FieldValidator()
    .required('Email is required')
    .email('Enter a valid email address');

// In a form:
TextFormField(
  controller: emailController,
  validator: emailValidator.asFunction,
);

// Anywhere else:
final error = emailValidator.validate(emailController.text);
if (error != null) {
  // Show `error` to the user.
}

A FieldValidator is callable, so you can also write validator: FieldValidator().required().email().asFunction.

Built-in rules #

Rule Description
required([message]) Value must not be null, empty, or whitespace.
email([message]) Value must be a valid email address.
url([message]) Value must be a valid URL (scheme optional).
numeric([message]) Value must be an integer or decimal number.
numericRange(min, max, {message}) Number must fall within an inclusive range; either bound may be null.
integer([message]) Value must be a whole number.
minLength(min, [message]) Trimmed value must have at least min characters.
maxLength(max, [message]) Trimmed value must have at most max characters.
lengthBetween(min, max, [message]) Trimmed length must be within [min, max].
exactLength(length, [message]) Trimmed value must be exactly length characters.
strongPassword({...}) Password must satisfy configurable character requirements.
matches(() => other, [message]) Value must equal a lazily-evaluated other value.
matchesValue(other, [message]) Value must equal a fixed value.
pattern(RegExp, [message]) Value must match a regular expression.
contains(substring, [message]) Value must contain a substring.
equals(expected, {caseSensitive, message}) Value must equal an expected string.
oneOf(values, {caseSensitive, message}) Value must be one of a set of options.
alphabetic([message]) Value must contain only letters.
alphanumeric([message]) Value must contain only letters and digits.
custom((value) => ..., {skipOnEmpty}) Run any function returning null or an error message.

Rules that validate a format or length skip empty values, so they are safe to chain on optional fields. Add required() when the field is mandatory.

Common recipes #

Confirm password #

final confirmValidator = FieldValidator()
    .required('Please confirm your password')
    .matches(() => passwordController.text, 'Passwords do not match');

The matches callback is evaluated at validation time, so it always reads the current password.

Strong password #

final passwordValidator = FieldValidator().strongPassword(
  minLength: 10,
  requireSpecialCharacter: false,
);

By default it requires at least 8 characters plus an uppercase letter, a lowercase letter, a number, and a special character. Each requirement can be toggled.

Age / numeric range #

final ageValidator = FieldValidator()
    .required('Age is required')
    .integer('Whole numbers only')
    .numericRange(18, 120, message: 'You must be between 18 and 120');

Custom rule #

final noAdminValidator = FieldValidator().custom(
  (value) =>
      value!.contains('admin') ? 'Admin emails are not allowed' : null,
);

Collecting every error #

By default validate() returns only the first failing message. Enable aggregation to return them all joined by a separator:

final validator = FieldValidator(
  aggregate: true,
  separator: '\n',
)
    .required('Field cannot be blank')
    .email('Enter a valid email address');

// Or configure it fluently:
final same = FieldValidator()
    .required('Field cannot be blank')
    .email('Enter a valid email address')
    .aggregate(separator: ' • ');

For structured access, validateAll() always returns the full list and validateResult() returns a ValidationResult:

final result = validator.validateResult(input);
if (result.isInvalid) {
  for (final message in result.errors) {
    debugPrint(message);
  }
}

Localization #

Every default message lives on ValidationMessages. Override the ones you need once at start-up, then continue to pass per-call overrides where it makes sense:

void main() {
  ValidationMessages.required = 'Este campo es obligatorio.';
  ValidationMessages.email = 'Introduce un correo válido.';
  ValidationMessages.mismatch = 'Los valores no coinciden.';
  runApp(const MyApp());
}

String extensions #

For quick checks outside a form, import the library and use the extensions:

'a@b.com'.isValidEmail;      // true
'https://a.com'.isValidUrl;  // true
'3.14'.isNumeric;            // true
'42'.isInteger;              // true
'Abcd123!'.isStrongPassword; // true
'   '.isBlank;               // true (null-aware)
'ab1'.isAlphanumeric;        // true

// Normalize optional input:
final value = input.trimmedOrNull; // null when blank

You can also delegate to a validator with validateWith:

final error = input.validateWith(
  FieldValidator().required().email(),
);

Single-rule helpers #

When one rule is all you need, Validators returns a plain String? Function(String?):

TextFormField(validator: Validators.email());
TextFormField(validator: Validators.minLength(3, 'Too short'));

Example #

The example/ directory contains a runnable app with a full registration form (every built-in rule in context) and a live playground that validates as you type:

cd example
flutter run

API overview #

  • FieldValidator (alias MultiValidator) — the fluent builder.
  • ValidationRule — a single immutable rule; extend the package with addRule.
  • ValidationResultisValid, errors, firstError.
  • ValidationMessages — overridable default messages.
  • Validators — single-rule factory helpers.
  • String extensions on String and String?.

Author and Contact #

Developed and maintained by Ebrahim Joy.

Contributing #

Please report bugs and request features through the issue tracker. Pull requests are welcome.

License #

Released under the MIT License.

1
likes
160
points
75
downloads

Documentation

API reference

Publisher

verified publishereebrahimjoy.com

Weekly Downloads

A zero-dependency, fluent form validation toolkit for Dart and Flutter. Chain rules for email, password, length, range, and custom logic.

Repository (GitHub)
View/report issues

Topics

#validation #form #validator #flutter #dart

License

MIT (license)

More

Packages that depend on validate_kit