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 โ
TextInputFormatterfor 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
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
- Fork the repository
- Create your feature branch (
git checkout -b feature/my-feature) - Commit your changes (
git commit -m 'Add my feature') - Push to the branch (
git push origin feature/my-feature) - 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.
Libraries
- best_form_validator
- A comprehensive Flutter package for form validation.