VooForms
A comprehensive, type-safe forms package for Flutter with clean architecture, atomic design pattern, and excellent developer experience.
โจ Features
- ๐ฏ Type-Safe Fields - Full type safety with generics throughout
- ๐๏ธ Clean Architecture - Follows SOLID principles with clear separation of concerns
- ๐จ Atomic Design - Components organized as atoms, molecules, and organisms
- ๐ฑ Cross-Platform - Works seamlessly on iOS, Android, Web, Desktop
- ๐จ Material 3 - Built with the latest Material Design guidelines
- โ Rich Validators - 13+ built-in validators with composable validation
- ๐ง Smart Formatters - 12+ formatters for phone, credit card, currency, etc.
- ๐ฎ Powerful Controller - Advanced form state management
- ๐ Multiple Layouts - Vertical, grid, stepped, tabbed layouts
- ๐ Excellent DX - Intuitive API with great IDE support
๐ฆ Installation
Add voo_forms to your pubspec.yaml:
dependencies:
voo_forms: ^0.3.2
๐ Quick Start
Simple Form Example
import 'package:voo_forms/voo_forms.dart';
// Create a form using direct widget instantiation
final form = VooForm(
fields: [
VooTextField(
name: 'username',
label: 'Username',
validators: [
RequiredValidation(),
MinLengthValidation(minLength: 3),
],
),
VooEmailField(
name: 'email',
label: 'Email Address',
validators: [
RequiredValidation(),
EmailValidation(),
],
),
VooPasswordField(
name: 'password',
label: 'Password',
validators: [
RequiredValidation(),
MinLengthValidation(minLength: 8),
PatternValidation(
pattern: r'^(?=.*[A-Z])(?=.*[0-9])',
errorMessage: 'Must contain uppercase and number',
),
],
),
],
);
Organizing Fields with Sections
// Group related fields in collapsible sections
final form = VooForm(
fields: [
VooFormSection(
title: 'Personal Information',
description: 'Enter your basic details',
isCollapsible: true,
children: [
VooTextField(name: 'firstName', placeholder: 'First Name'),
VooTextField(name: 'lastName', placeholder: 'Last Name'),
VooDateField(name: 'birthDate', label: 'Date of Birth'),
],
),
VooFormSection(
title: 'Contact Details',
children: [
VooEmailField(name: 'email', label: 'Email'),
VooPhoneField(name: 'phone', label: 'Phone'),
],
),
],
);
๐จ Field Types
VooForms provides direct widget classes for all field types:
// Text Fields
VooTextField(name: 'username', label: 'Username')
VooEmailField(name: 'email', label: 'Email')
VooPasswordField(name: 'password', label: 'Password')
VooPhoneField(name: 'phone', label: 'Phone')
VooMultilineField(name: 'bio', label: 'Bio')
VooNumberField(name: 'age', label: 'Age')
// Selection Fields
VooDropdownField<String>(
name: 'country',
label: 'Country',
options: ['United States', 'United Kingdom', 'Canada'],
)
VooCheckboxField(name: 'terms', label: 'Accept Terms')
VooBooleanField(name: 'newsletter', label: 'Subscribe')
// Date & Time
VooDateField(name: 'birthday', label: 'Birthday')
VooDateFieldButton(name: 'appointment', label: 'Appointment Date')
// Numeric Fields
VooIntegerField(name: 'age', label: 'Age')
VooDecimalField(name: 'price', label: 'Price')
VooCurrencyField(name: 'salary', label: 'Salary')
VooPercentageField(name: 'discount', label: 'Discount')
// Other Types
VooFileField(name: 'avatar', label: 'Avatar')
VooListField<String>(
name: 'tags',
label: 'Tags',
items: tags,
itemBuilder: (tag) => Chip(label: Text(tag)),
)
โ Validators
Built-in Validators
Each validator is in its own file for better organization:
// Basic Validators
RequiredValidation()
EmailValidation()
PhoneValidation()
UrlValidation()
// String Validators
MinLengthValidation(minLength: 3)
MaxLengthValidation(maxLength: 50)
PatternValidation(pattern: r'^[A-Z]', errorMessage: 'Must start with capital')
// Numeric Validators
MinValueValidation(minValue: 0)
MaxValueValidation(maxValue: 100)
RangeValidation(minValue: 0, maxValue: 100)
// Date Validators
DateRangeValidation(
minDate: DateTime(2020),
maxDate: DateTime(2030),
)
// Custom Validation
CustomValidation(
validator: (value) {
if (value == 'admin') return 'Username not available';
return null;
},
)
// Combine Multiple Validators
CompoundValidation(rules: [
RequiredValidation(),
EmailValidation(),
])
Creating Custom Validators
class PasswordMatchValidation extends VooValidationRule<String> {
final String Function() getPassword;
PasswordMatchValidation({required this.getPassword})
: super(errorMessage: 'Passwords do not match');
@override
String? validate(String? value) {
if (value != getPassword()) {
return errorMessage;
}
return null;
}
}
๐ง Formatters
Smart input formatting for better UX:
// Phone Formatters
VooFormatters.phoneUS() // (123) 456-7890
VooFormatters.phoneInternational() // +1 234 567 8900
// Card & Financial
VooFormatters.creditCard() // 1234 5678 9012 3456
VooFormatters.currency(symbol: '\$') // $1,234.56
// Date Formatters
VooFormatters.dateUS() // MM/DD/YYYY
VooFormatters.dateEU() // DD/MM/YYYY
VooFormatters.dateISO() // YYYY-MM-DD
// Text Formatters
VooFormatters.uppercase()
VooFormatters.lowercase()
VooFormatters.alphanumeric()
VooFormatters.numbersOnly()
// US Specific
VooFormatters.ssn() // 123-45-6789
VooFormatters.zipCode() // 12345 or 12345-6789
// Custom Patterns
VooFormatters.mask('###-##-####') // Custom mask
VooFormatters.pattern(
pattern: 'AA-####',
patternMapping: {
'A': RegExp(r'[A-Z]'),
'#': RegExp(r'[0-9]'),
},
)
๐ญ Field Options
Customize field appearance and behavior:
VooField.text(
name: 'username',
options: VooFieldOptions(
// Label positioning
labelPosition: LabelPosition.floating, // or above, left, placeholder, hidden
// Field styling
fieldVariant: FieldVariant.filled, // or outlined, underlined, ghost, rounded, sharp
// Validation behavior
validateOnChange: true,
validateOnFocusLost: true,
// Error display
errorDisplayMode: ErrorDisplayMode.always, // or onFocus, onSubmit
// Focus behavior
focusBehavior: FocusBehavior.next, // or submit, none
),
)
Preset Options
Use built-in presets for consistency:
options: VooFieldOptions.material // Material Design defaults
options: VooFieldOptions.comfortable // Spacious layout
options: VooFieldOptions.compact // Dense layout
options: VooFieldOptions.minimal // Minimal styling
๐ฎ Form Controller
Advanced form control:
final controller = VooFormController(
form: form,
onFieldChange: (field, value) {
print('${field.name} changed to $value');
},
onValidationChange: (isValid) {
print('Form valid: $isValid');
},
);
// Programmatic control
controller.setValue('username', 'john_doe');
controller.getValue('username'); // 'john_doe'
controller.validate(); // Validate all fields
controller.validateField('email'); // Validate specific field
controller.reset(); // Reset to initial values
controller.clear(); // Clear all values
controller.submit(); // Submit the form
// Field management
controller.enableField('email');
controller.disableField('password');
controller.showField('optional');
controller.hideField('advanced');
controller.focusField('username');
๐ Layouts
Multiple layout options:
Vertical Layout (Default)
VooFormVerticalLayout(
fields: fields,
spacing: 16.0,
)
Grid Layout
VooFormGridLayout(
fields: fields,
columns: 2,
spacing: 16.0,
crossAxisSpacing: 12.0,
)
Stepped Layout (Wizard)
VooFormSteppedLayout(
steps: [
VooFormStep(
title: 'Personal Info',
fields: [/* fields */],
),
VooFormStep(
title: 'Contact',
fields: [/* fields */],
),
],
)
Tabbed Layout
VooFormTabbedLayout(
tabs: [
VooFormTab(
label: 'Basic',
fields: [/* fields */],
),
VooFormTab(
label: 'Advanced',
fields: [/* fields */],
),
],
)
๐ Async Options & Search
Support for dynamic dropdown options:
// Async dropdown with search
VooField.dropdown<City>(
name: 'city',
label: 'City',
enableSearch: true,
asyncOptionsLoader: (query) async {
final cities = await api.searchCities(query);
return cities.map((city) => VooFieldOption(
value: city,
label: city.name,
subtitle: city.state,
icon: Icons.location_city,
)).toList();
},
)
๐งช Testing
VooForms is designed for easy testing:
testWidgets('Form submission', (tester) async {
final form = VooForm(
fields: [
VooField.text(name: 'username'),
VooField.email(name: 'email'),
],
onSubmit: expectAsync1((values) {
expect(values['username'], 'testuser');
expect(values['email'], 'test@example.com');
}),
);
await tester.pumpWidget(MaterialApp(home: form));
// Enter values
await tester.enterText(
find.byType(TextFormField).first,
'testuser',
);
await tester.enterText(
find.byType(TextFormField).last,
'test@example.com',
);
// Submit
await tester.tap(find.text('Submit'));
await tester.pump();
});
๐๏ธ Architecture
VooForms follows clean architecture principles:
Presentation Layer (UI/Widgets)
โ
Domain Layer (Entities/Business Logic)
โ
Data Layer (Models/Repositories)
Atomic Design Pattern
- Atoms: Basic input widgets (text field, checkbox, etc.)
- Molecules: Composed components (field with label, field with error)
- Organisms: Complete forms and layouts
Key Principles
- One class per file - Better organization and navigation
- No _buildXXX methods - Using helper classes instead
- Clean imports - No relative imports, properly ordered
- Type safety - Generics used throughout
- SOLID principles - Single responsibility, open/closed, etc.
๐จ Theming
VooForms respects your app's Material theme:
MaterialApp(
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
useMaterial3: true,
),
home: MyApp(),
)
๐ Documentation
- Developer Guide - Comprehensive guide with examples
- API Documentation - Full API reference
- Example App - Complete example implementation
- Changelog - Version history
๐ค Contributing
Contributions welcome! Please ensure:
- Follow clean architecture principles
- One class per file
- No _buildXXX methods returning widgets
- Add tests for new features
- Update documentation
๐ License
MIT License - see LICENSE file for details.
Built by VooStack
Need help with Flutter development or custom form solutions?
VooStack builds enterprise Flutter applications and developer tools. We're here to help with your next project.
๐ What's New in 0.1.14
- Major Technical Debt Cleanup - Eliminated all _buildXXX methods
- Better Organization - 25+ classes split into individual files
- Improved DX - Each validator/formatter in its own file
- Clean Architecture - Proper separation of concerns throughout
- Enhanced Testing - 92.6% test success rate
See CHANGELOG.md for full details.