Formix All
The complete validation ecosystem for Dart & Flutter. One import gives you everything you need for type-safe, composable, and testable form validation.
What's Included
This umbrella package re-exports all Formix packages:
| Package | Description |
|---|---|
| formix_core | Core validation engine with composable rules |
| formix_validators | 50+ built-in validators for strings, numbers, dates, etc. |
| formix_flutter | Flutter integration for TextFormField and forms |
| formix_test | Testing utilities, matchers, and mocks |
Installation
dependencies:
formix_all: ^0.1.0
flutter pub get
Quick Start
import 'package:formix_all/formix_all.dart';
// Define validators
final emailValidator = Validate.all<String, String>([
StringRules.required(error: 'Email is required'),
StringRules.email(error: 'Invalid email format'),
]);
final passwordValidator = Validate.all<String, String>([
StringRules.required(error: 'Password is required'),
StringRules.minLength(8, error: 'At least 8 characters'),
StringRules.hasUppercase(error: 'Need uppercase letter'),
StringRules.hasDigit(error: 'Need a number'),
]);
// Use in Flutter forms
TextFormField(
decoration: const InputDecoration(labelText: 'Email'),
validator: emailValidator.toFieldValidator(),
)
// Or validate directly
final result = emailValidator.validate('test@example.com');
if (result.isValid) {
print('Valid: ${result.value}');
} else {
print('Errors: ${result.errors}');
}
Features
🎯 Type-Safe Validation
// Custom error types for i18n
enum EmailError { required, invalid, tooLong }
final validator = Validate.all<String, EmailError>([
StringRules.required(error: EmailError.required),
StringRules.email(error: EmailError.invalid),
]);
// Pattern match on results
switch (validator.validate(input)) {
case Valid(:final value):
saveEmail(value);
case Invalid(:final error):
showError(formatError(error));
}
🔗 Composable Rules
// Combine validators
final validator = Validate.all<String, String>([...]); // AND logic
final validator = Validate.any<String, String>([...]); // OR logic
final validator = rule1.andThen(rule2); // Sequential
final validator = rule.when((v) => v.isNotEmpty); // Conditional
final validator = rule.optional(); // Skip if null
⚡ Performance Optimized
// Cache validation results
final cached = validator.cached();
final lruCached = validator.lruCached(maxSize: 100);
// Use with real-time validation
TextFormField(
validator: cached.toFieldValidator(),
autovalidateMode: AutovalidateMode.onUserInteraction,
)
🧪 Testing Utilities
import 'package:formix/formix.dart';
import 'package:test/test.dart';
test('email validation', () {
expect(emailValidator.validate('test@example.com'), isValid());
expect(emailValidator.validate('invalid'), isInvalid());
expect(emailValidator.validate(''), hasError('Email is required'));
});
Available Validators
StringRules
required, email, url, uuid, creditCard, minLength, maxLength, matches, contains, startsWith, endsWith, hasUppercase, hasLowercase, hasDigit, hasSpecialChar, alphanumeric, digitsOnly, and more.
NumberRules
min, max, range, positive, negative, integer, multipleOf, precision, and more.
DateRules
past, future, before, after, between, age, minimumAge, weekday, weekend, businessDay, and more.
CollectionRules
minLength, maxLength, notEmpty, unique, contains, every, any, and more.
PhoneRules
e164, usPhone, custom, and more.
FileRules
maxSize, extension, mimeType, imageOnly, documentOnly, and more.
Selective Imports
If you don't need everything, import only what you need:
// Core only (no Flutter, no validators)
import 'package:formix_core/formix_core.dart';
// Flutter integration only
import 'package:formix_flutter/formix_flutter.dart';
// Specific validator categories
import 'package:formix_validators/string.dart';
import 'package:formix_validators/number.dart';
import 'package:formix_validators/date.dart';
Complete Example
import 'package:flutter/material.dart';
import 'package:formix/formix.dart';
class RegistrationForm extends StatefulWidget {
const RegistrationForm({super.key});
@override
State<RegistrationForm> createState() => _RegistrationFormState();
}
class _RegistrationFormState extends State<RegistrationForm> {
final _formKey = GlobalKey<FormState>();
static final _emailValidator = Validate.all<String, String>([
StringRules.required(error: 'Email is required'),
StringRules.email(error: 'Invalid email format'),
]);
static final _passwordValidator = Validate.allCollect<String, String>([
StringRules.required(error: 'Password is required'),
StringRules.minLength(8, error: 'At least 8 characters'),
StringRules.hasUppercase(error: 'Need uppercase letter'),
StringRules.hasDigit(error: 'Need a number'),
]);
@override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Column(
children: [
TextFormField(
decoration: const InputDecoration(labelText: 'Email'),
validator: _emailValidator.toFieldValidator(),
),
const SizedBox(height: 16),
TextFormField(
decoration: const InputDecoration(labelText: 'Password'),
obscureText: true,
validator: _passwordValidator.toFieldValidator(),
),
const SizedBox(height: 24),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
// Form is valid!
}
},
child: const Text('Register'),
),
],
),
);
}
}
Documentation
- formix_core README - Core concepts and API
- formix_validators README - All available validators
- formix_flutter README - Flutter integration guide
- formix_test README - Testing guide
License
MIT License - see LICENSE file for details.
Made with ❤️ by Fady Fayez Younan