best_form_validator 1.4.0
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 #
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 #
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 #
- 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.