best_form_validator 1.4.0 copy "best_form_validator: ^1.4.0" to clipboard
best_form_validator: ^1.4.0 copied to clipboard

Zero-initialization Flutter form validation: email, url, phone (52 countries, local & international formats), password strength, Unicode names, age, date, strict time, credit card (Luhn), IBAN (MOD-97 [...]

best_form_validator #

pub package License pub points

Demo #

Best Form Validator Demo

A high-performance, zero-initialization form validation package for Flutter and Dart.

Instant. Context-free. No async setup.
Drop validators directly into TextFormField.validator โ€” no BuildContext, no await, no boilerplate.

Why best_form_validator? #

Feature Standard Flutter best_form_validator
Phone regex Write your own Built-in 52 countries ๐ŸŒ
Local number formats Manual conversion Auto-normalized โœ…
Async startup N/A Zero-init (synchronous) ๐Ÿš€
Translations Manual if-else 25 languages built-in
Chaining validators Nested callbacks MultiValidator([...])
URL validation Write your own Built-in HTTP/HTTPS โœ…
Financial validation External packages Native Luhn / IBAN ๐Ÿ’ณ
Unicode names ASCII regex only Arabic, CJK, Devanagariโ€ฆ

Features #

  • Zero-Initialization โ€” synchronous, no startup code required
  • Phone Validation โ€” 52 countries, accepts local formats (03001234567) and international formats (+923001234567)
  • GB / UK alias โ€” both 'GB' (ISO 3166-1) and 'UK' work interchangeably
  • Email & Password โ€” battle-tested regex + configurable strength rules
  • URL Validation โ€” HTTP/HTTPS URLs with proper scheme and host checks
  • Password Strength โ€” PasswordValidator.getPasswordStrength() returns a 0โ€“5 score
  • Unicode Names โ€” Latin, Arabic, Urdu, Hindi, Chinese, Japanese, Korean, and more
  • Age Validation โ€” handles the birthday-not-yet-occurred edge case correctly
  • Time Validation โ€” strict HH:mm / HH:mm:ss (rejects 25:99:99)
  • Financial Checks โ€” Credit Card (Luhn Mod-10) & IBAN (MOD-97), both publicly exported
  • MultiValidator โ€” chain validators, returns the first error
  • Localization โ€” 25 language error messages, runtime-switchable
  • PhoneInputFormatter โ€” TextInputFormatter for auto-spacing phone numbers

Installation #

dependencies:
  best_form_validator: ^1.4.0
flutter pub get

Quick Start #

import 'package:best_form_validator/best_form_validator.dart';

TextFormField(
  validator: (value) => Validators.validateEmail(value),
)

No initialization needed. Works immediately.


Localization Setup #

Add FormLocalizations.delegate to your MaterialApp and call Validators.setLocale in the builder:

import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:best_form_validator/best_form_validator.dart';

MaterialApp(
  localizationsDelegates: [
    GlobalMaterialLocalizations.delegate,
    GlobalWidgetsLocalizations.delegate,
    GlobalCupertinoLocalizations.delegate,
    FormLocalizations.delegate,
  ],
  supportedLocales: const [
    Locale('en'), Locale('es'), Locale('fr'), Locale('de'),
    Locale('ar'), Locale('ur'), Locale('hi'), Locale('zh'),
    Locale('pt'), Locale('ru'), Locale('it'), Locale('tr'),
    Locale('ja'), Locale('ko'), Locale('id'), Locale('ms'),
    Locale('th'), Locale('vi'), Locale('nl'), Locale('sv'),
    Locale('no'), Locale('fi'), Locale('da'), Locale('el'),
    Locale('fa'),
  ],
  builder: (context, child) {
    Validators.setLocale(Localizations.localeOf(context));
    return child!;
  },
)

Usage #

Email #

Validators.validateEmail('user@example.com');  // null (valid)
Validators.validateEmail('');                  // 'Email is required'
Validators.validateEmail('bad-email');         // 'Enter a valid email'

// Custom messages
Validators.validateEmail(
  'bad',
  requiredError: 'Please enter your email',
  invalidError: 'That email looks wrong',
);

URL #

Validators.validateUrl('https://example.com');   // null (valid)
Validators.validateUrl('http://localhost:8080'); // null (valid)
Validators.validateUrl('example.com');           // error (missing scheme)
Validators.validateUrl('');                      // 'URL is required'

// Accept bare domains (prepends https://)
Validators.validateUrl('example.com', allowMissingScheme: true); // null (valid)

// Optional field
Validators.validateUrl('', isRequired: false);  // null (valid)

// Custom messages
Validators.validateUrl(
  'bad',
  requiredError: 'Please enter your website',
  invalidError: 'That URL looks wrong',
);

Phone โ€” international & local formats #

Both +923001234567 and 03001234567 are accepted for Pakistan:

// International format
Validators.validatePhone('+12025551234', 'US');      // null (valid)
Validators.validatePhone('+923001234567', 'PK');     // null (valid)

// Local format โ€” auto-normalized before validation
Validators.validatePhone('03001234567', 'PK');       // null (valid)
Validators.validatePhone('07911123456', 'GB');       // null (valid)

// Both GB and UK are accepted for the United Kingdom
Validators.validatePhone('+447911123456', 'GB');     // null (valid)
Validators.validatePhone('+447911123456', 'UK');     // null (valid)

Normalize a local number to international format independently:

String intl = Validators.normalizePhone('03001234567', 'PK');
// โ†’ '+923001234567'

Supported countries (52): US, CA, GB, UK, FR, DE, IN, AU, BR, CN, JP, MX, RU, ZA, NG, EG, KE, GH, SA, AE, IT, ES, SE, NO, FI, DK, NL, BE, CH, AT, PT, GR, TR, IR, PK, BD, LK, TH, MY, SG, ID, PH, VN, KR, HK, TW, NZ, AF, AL, DZ, AR, AZ, BH

TextFormField(
  decoration: InputDecoration(labelText: 'Phone', hintText: '+1 234 567 8900'),
  inputFormatters: [PhoneInputFormatter()],       // auto-formats as user types
  validator: (v) => Validators.validatePhone(v, 'US'),
  keyboardType: TextInputType.phone,
)

Password #

// Basic (min 6 chars)
Validators.validatePassword('secret');

// Full strength check
Validators.validatePassword(
  'MyP@ssw0rd',
  checkLength: true,
  minLength: 8,
  checkNumberAndLetter: true,
  checkSpecialCharacter: true,
  checkLowerCase: true,
  checkUpperCase: true,
);

// Password strength score (0โ€“5)
int score = PasswordValidator.getPasswordStrength('MyP@ssw0rd'); // 5

Name โ€” Unicode aware #

Validators.validateName('John Doe');      // null โ€“ Latin
Validators.validateName('Josรฉ Garcรญa');   // null โ€“ accented
Validators.validateName('ู…ุญู…ุฏ ุนู„ูŠ');     // null โ€“ Arabic
Validators.validateName('็Ž‹่Šณ');          // null โ€“ Chinese
Validators.validateName('เคฐเคพเคœ เค•เฅเคฎเคพเคฐ');    // null โ€“ Hindi (Devanagari)
Validators.validateName('Mary-Jane');    // null โ€“ hyphenated
Validators.validateName("O'Brien");      // null โ€“ apostrophe
Validators.validateName('John123');      // error โ€“ digits not allowed

Age #

Validators.validateAge('2000-01-15', 18);          // null if โ‰ฅ18
Validators.validateAge(DateTime(2000, 1, 15), 18); // DateTime also accepted

Validators.validateAge(
  '2010-06-01',
  18,
  invalidError: 'You must be at least 18 years old',
);

Date #

Validators.validateDate('2024-01-15'); // null (valid)
Validators.validateDate('not-a-date'); // error

Time #

Validators.validateTime('14:30');      // null โ€“ HH:mm
Validators.validateTime('14:30:00');   // null โ€“ HH:mm:ss
Validators.validateTime('25:99:99');   // error โ€“ out of range (fixed in v1.3.0)
Validators.validateTime('00:00:00');   // null โ€“ midnight

Financial โ€” Credit Card & IBAN #

// Credit card (Luhn Mod-10) โ€” spaces and dashes stripped automatically
Validators.validateCreditCard('4111 1111 1111 1111'); // null (valid Visa test)
Validators.validateCreditCard('1234 5678 9012 3456'); // error

// Direct class usage
FinancialValidators.validateCreditCard('4111111111111111');

// IBAN (MOD-97) โ€” spaces stripped, case-insensitive
Validators.validateIBAN('GB82 WEST 1234 5698 7654 32'); // null (valid)
Validators.validateIBAN('INVALID');                      // error

// In a TextFormField
TextFormField(
  validator: (v) => Validators.validateCreditCard(v),
  keyboardType: TextInputType.number,
)

MultiValidator โ€” chain validators #

TextFormField(
  validator: MultiValidator([
    (v) => Validators.validateName(v),
    (v) => (v != null && v.length < 2) ? 'Too short' : null,
  ]),
)

Complete Form Example #

import 'package:flutter/material.dart';
import 'package:best_form_validator/best_form_validator.dart';

class RegistrationForm extends StatefulWidget {
  const RegistrationForm({super.key});
  @override
  State<RegistrationForm> createState() => _RegistrationFormState();
}

class _RegistrationFormState extends State<RegistrationForm> {
  final _formKey = GlobalKey<FormState>();

  void _submit() {
    if (_formKey.currentState!.validate()) {
      ScaffoldMessenger.of(context)
          .showSnackBar(const SnackBar(content: Text('Success!')));
    }
  }

  @override
  Widget build(BuildContext context) {
    return Form(
      key: _formKey,
      child: ListView(
        padding: const EdgeInsets.all(16),
        children: [
          TextFormField(
            decoration: const InputDecoration(labelText: 'Full Name'),
            validator: (v) => Validators.validateName(v),
          ),
          const SizedBox(height: 12),
          TextFormField(
            decoration: const InputDecoration(labelText: 'Email'),
            validator: (v) => Validators.validateEmail(v),
            keyboardType: TextInputType.emailAddress,
          ),
          const SizedBox(height: 12),
          TextFormField(
            decoration: const InputDecoration(
              labelText: 'Phone',
              hintText: '+1 555 000 0000 or local format',
            ),
            inputFormatters: [PhoneInputFormatter()],
            validator: (v) => Validators.validatePhone(v, 'US'),
            keyboardType: TextInputType.phone,
          ),
          const SizedBox(height: 12),
          TextFormField(
            decoration: const InputDecoration(
              labelText: 'Password',
              helperText: 'Min 8 chars, upper, lower, number, special',
            ),
            obscureText: true,
            validator: (v) => Validators.validatePassword(
              v,
              checkLength: true,
              minLength: 8,
              checkNumberAndLetter: true,
              checkSpecialCharacter: true,
              checkLowerCase: true,
              checkUpperCase: true,
            ),
          ),
          const SizedBox(height: 12),
          TextFormField(
            decoration: const InputDecoration(
              labelText: 'Birth Date',
              hintText: 'yyyy-MM-dd',
            ),
            validator: (v) => Validators.validateAge(v, 18,
                invalidError: 'Must be at least 18 years old'),
          ),
          const SizedBox(height: 24),
          ElevatedButton(
            onPressed: _submit,
            child: const Text('Register'),
          ),
        ],
      ),
    );
  }
}

API Reference #

Validators (convenience faรงade) #

Method Description
validateEmail(value) Standard email format
validateUrl(value, {...}) HTTP/HTTPS URL with scheme and host checks
validatePhone(value, isoCode) 52 countries, auto-normalizes local formats
normalizePhone(value, isoCode) Convert local to international format
validatePassword(value, {...}) Configurable password rules
validateName(value) Unicode-aware name validation
validateAge(value, minimumAge) Minimum age from birth date
validateDate(value) Parseable date string
validateTime(value) Strict HH:mm or HH:mm:ss
validateCreditCard(value) Luhn algorithm (Mod-10)
validateIBAN(value) ISO 13616 MOD-97
setLocale(locale) Set global error message language

PasswordValidator #

Method Description
validate(value, {...}) Same as Validators.validatePassword
getPasswordStrength(value) Returns int 0โ€“5 entropy score

PhoneValidator #

Method Description
validatePhoneNumber(value, isoCode) Direct phone validation
normalizePhone(value, isoCode) Local โ†’ international conversion

UrlValidator #

Method Description
validate(value, {...}) Same as Validators.validateUrl

FinancialValidators #

Method Description
validateCreditCard(value) Luhn check, strips spaces/dashes
validateIBAN(value) MOD-97 check, strips spaces

MultiValidator #

MultiValidator([validator1, validator2, ...])

Calls each validator in order and returns the first non-null error.

PhoneInputFormatter #

A TextInputFormatter that auto-spaces phone numbers as the user types (+XXX XXX XXX XXX).


Supported Languages (25) #

en es fr de ar ur hi zh pt ru it tr ja ko id ms th vi nl sv no fi da el fa


Platform Support #

Android iOS Web Windows macOS Linux
โœ… โœ… โœ… โœ… โœ… โœ…

Requirements #

  • Dart SDK: >=3.0.0 <4.0.0
  • Flutter: >=3.0.0
  • Dependencies: intl ^0.20.2 (only direct dependency)

Contributing #

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/my-feature)
  3. Commit your changes (git commit -m 'Add my feature')
  4. Push to the branch (git push origin feature/my-feature)
  5. Open a Pull Request

Please file bugs and feature requests in our issue tracker.


License #

MIT โ€” see LICENSE.


Maintained By #

GreeLogix โ€” Flutter, Laravel & AI Development Agency
๐ŸŒ https://greelogix.com
๐Ÿ“ฉ hello@greelogix.com


Other Flutter Packages by GreeLogix #

Package Description
quick_popup_manager Smart popup, dialog & overlay management
smart_form_toolkit Advanced form toolkit with ready-to-use widgets
safe_json_mapper Type-safe JSON parsing and mapping
flutter_telescope Debugging, logging & app insights toolkit

See CHANGELOG.md for a full history of changes.

11
likes
150
points
205
downloads

Documentation

API reference

Publisher

verified publishergreelogix.com

Weekly Downloads

Zero-initialization Flutter form validation: email, url, phone (52 countries, local & international formats), password strength, Unicode names, age, date, strict time, credit card (Luhn), IBAN (MOD-97), MultiValidator chaining, and 25-language localization.

Repository (GitHub)
View/report issues

Topics

#form #validator #url #phone #password

License

MIT (license)

Dependencies

flutter, flutter_localizations, intl

More

Packages that depend on best_form_validator