indo_form_validator 1.0.0
indo_form_validator: ^1.0.0 copied to clipboard
Production-ready form validation utilities for Indonesian applications. Supports phone numbers, NIK, NPWP, and email validation.
indo_form_validator #
A lightweight form validation library for Indonesian applications. Provides validators for phone numbers, NIK, NPWP, and email with bilingual error messages.
Features #
- Phone number validation (Indonesian formats: 08xx, +62, 62)
- NIK validation (16 digits with optional region code checking)
- NPWP validation (15 digits with formatting support)
- Email validation (RFC 5322 compliant)
- Bilingual error messages (Indonesian and English)
- Validator chaining and custom validators
- Strict validation mode
- Null-safe and zero dependencies
- Direct Flutter Form integration
Installation #
Add to your pubspec.yaml:
dependencies:
indo_form_validator: ^1.0.0
Then run:
flutter pub get
Usage #
Basic Form Validation #
import 'package:indo_form_validator/indo_form_validator.dart';
TextFormField(
decoration: const InputDecoration(labelText: 'Phone Number'),
validator: IndoValidator.phone(),
)
TextFormField(
decoration: const InputDecoration(labelText: 'NIK'),
validator: IndoValidator.nik(),
)
TextFormField(
decoration: const InputDecoration(labelText: 'NPWP'),
validator: IndoValidator.npwp(),
)
TextFormField(
decoration: const InputDecoration(labelText: 'Email'),
validator: IndoValidator.email(),
)
English Error Messages #
TextFormField(
validator: IndoValidator.phone(
config: ValidationConfig.english,
),
)
Strict Validation Mode #
// NIK with region code validation
TextFormField(
validator: IndoValidator.nik(
config: ValidationConfig.strictMode,
validateRegion: true,
),
)
// NPWP with format validation
TextFormField(
validator: IndoValidator.npwp(
config: ValidationConfig.strictMode,
),
)
Validator Chaining #
TextFormField(
validator: IndoValidator.chain([
IndoValidator.phone(),
(value) {
final cleaned = value?.replaceAll(RegExp(r'[\s\-]'), '');
return cleaned?.length == 12 ? null : 'Must be 12 digits';
},
]),
)
Custom Validators #
TextFormField(
validator: IndoValidator.custom(
(value) => value?.startsWith('08') ?? false,
'Phone must start with 08',
),
)
Standalone Validation #
// Using ValidationResult
final result = IndoValidator.validatePhone('081234567890');
if (result.isValid) {
print('Phone is valid');
} else {
print('Error: ${result.message}');
}
// Using boolean check
if (PhoneValidator.isValid('081234567890')) {
print('Valid phone number');
}
// Direct validation
final nikResult = NikValidator.validate('3201234567890123');
print(nikResult.isValid); // true or false
print(nikResult.message); // error message or null
NPWP Formatting #
final formatted = NpwpValidator.format('123456789012345');
print(formatted); // 12.345.678.9-012.345
Validation Rules #
Phone Number #
- Supports formats:
08xxxxxxxxxx,+628xxxxxxxxxx,628xxxxxxxxxx - Length: 10-13 digits after prefix
- Automatically removes spaces, dashes, and parentheses
NIK (Nomor Induk Kependudukan) #
- Exactly 16 digits
- Numeric only
- Optional region code validation (province: 11-94)
- Supports formatted input with spaces/dashes
NPWP (Nomor Pokok Wajib Pajak) #
- Exactly 15 digits
- Numeric only
- Supports formatted (
XX.XXX.XXX.X-XXX.XXX) and non-formatted input - Strict mode validates format structure
Email #
- RFC 5322 compliant regex
- Strict mode checks for consecutive dots and valid TLD length
API Reference #
IndoValidator #
Main validator class providing convenient access to all validators.
// Form validators (returns String? for FormField)
IndoValidator.phone({ValidationConfig config})
IndoValidator.nik({ValidationConfig config, bool validateRegion})
IndoValidator.npwp({ValidationConfig config})
IndoValidator.email({ValidationConfig config})
// Validation methods (returns ValidationResult)
IndoValidator.validatePhone(String? value, {ValidationConfig config})
IndoValidator.validateNik(String? value, {ValidationConfig config, bool validateRegion})
IndoValidator.validateNpwp(String? value, {ValidationConfig config})
IndoValidator.validateEmail(String? value, {ValidationConfig config})
// Utility methods
IndoValidator.chain(List<String? Function(String?)> validators)
IndoValidator.custom(bool Function(String?) validationFunction, String errorMessage)
Individual Validators #
Each validator has three methods:
// Returns ValidationResult with isValid and message
PhoneValidator.validate(String? value, {ValidationConfig config})
// Returns String? for FormField.validator
PhoneValidator.validator({ValidationConfig config})
// Returns bool for quick checks
PhoneValidator.isValid(String? value)
ValidationConfig #
const ValidationConfig({
String language = 'id', // 'id' or 'en'
bool strict = false,
})
// Predefined configs
ValidationConfig.defaultConfig // Indonesian, non-strict
ValidationConfig.english // English, non-strict
ValidationConfig.strictMode // Indonesian, strict
ValidationResult #
class ValidationResult {
final bool isValid;
final String? message;
const ValidationResult.valid();
const ValidationResult.invalid(String message);
}
Complete Example #
class MyForm extends StatefulWidget {
@override
State<MyForm> createState() => _MyFormState();
}
class _MyFormState extends State<MyForm> {
final _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Column(
children: [
TextFormField(
decoration: const InputDecoration(labelText: 'Phone'),
validator: IndoValidator.phone(),
),
TextFormField(
decoration: const InputDecoration(labelText: 'NIK'),
validator: IndoValidator.nik(),
),
TextFormField(
decoration: const InputDecoration(labelText: 'NPWP'),
validator: IndoValidator.npwp(),
),
TextFormField(
decoration: const InputDecoration(labelText: 'Email'),
validator: IndoValidator.email(),
),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
// Form is valid
}
},
child: const Text('Submit'),
),
],
),
);
}
}
Testing #
Run tests:
flutter test
The package includes comprehensive unit tests covering valid and invalid inputs, edge cases, error messages in both languages, and strict mode validation.
Contributing #
Contributions are welcome. Please read CONTRIBUTING.md for details.
License #
This project is licensed under the MIT License - see the LICENSE file for details.
Changelog #
See CHANGELOG.md for a list of changes.