best_form_validator 1.1.0 copy "best_form_validator: ^1.1.0" to clipboard
best_form_validator: ^1.1.0 copied to clipboard

A comprehensive Flutter package for form validation with support for email, phone (50+ countries), password, name, age, date, time validation, and full localization support. Customizable error message [...]

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:best_form_validator/best_form_validator.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  // Initialize standard regex patterns for phone validation
  await Validators.loadPhoneRegex();
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => MyAppState();

  static MyAppState? of(BuildContext context) =>
      context.findAncestorStateOfType<MyAppState>();
}

class MyAppState extends State<MyApp> {
  Locale _locale = const Locale('en');

  void setLocale(Locale locale) {
    setState(() {
      _locale = locale;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Validation Tester',
      debugShowCheckedModeBanner: false,
      locale: _locale,
      localizationsDelegates: const [
        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) {
        // Update the static validator locale whenever the app locale changes
        final locale = Localizations.localeOf(context);
        Validators.setLocale(locale);
        return child!;
      },
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.teal),
        useMaterial3: true,
        inputDecorationTheme: InputDecorationTheme(
          border: OutlineInputBorder(borderRadius: BorderRadius.circular(12)),
          filled: true,
          fillColor: Colors.grey.shade50,
        ),
      ),
      home: const ValidationShowcasePage(),
    );
  }
}

class ValidationShowcasePage extends StatefulWidget {
  const ValidationShowcasePage({super.key});

  @override
  State<ValidationShowcasePage> createState() => _ValidationShowcasePageState();
}

class _ValidationShowcasePageState extends State<ValidationShowcasePage> {
  // Current selection
  String _selectedCase = 'Email Validation';

  // Form Key
  final _formKey = GlobalKey<FormState>();

  // Input Controllers
  final _textController = TextEditingController();

  // Specific State Variables
  String _selectedCountry = 'US';
  bool _obscureText = true;

  // Validation Result State
  String? _successMessage;

  // Available Cases
  final List<String> _cases = [
    'Email Validation',
    'Phone Validation',
    'Password Validation',
    'Name Validation',
    'Age Validation',
    'Date Validation',
    'Time Validation',
  ];

  final List<Map<String, String>> _countries = [
    {'code': 'US', 'name': 'USA (+1)'},
    {'code': 'UK', 'name': 'UK (+44)'},
    {'code': 'PK', 'name': 'Pakistan (+92)'},
    {'code': 'IN', 'name': 'India (+91)'},
    {'code': 'CA', 'name': 'Canada (+1)'},
    {'code': 'AU', 'name': 'Australia (+61)'},
    {'code': 'AE', 'name': 'UAE (+971)'},
  ];

  final Map<String, String> _languages = {
    'en': 'English',
    'es': 'Spanish',
    'fr': 'French',
    'de': 'German',
    'ar': 'Arabic',
    'ur': 'Urdu',
    'hi': 'Hindi',
    'ru': 'Russian',
  };

  @override
  void dispose() {
    _textController.dispose();
    super.dispose();
  }

  // Reset state when case changes
  void _onCaseChanged(String? newValue) {
    if (newValue != null && newValue != _selectedCase) {
      setState(() {
        _selectedCase = newValue;
        _textController.clear();
        _successMessage = null;
        _selectedCountry = 'US';
        _obscureText = true;
        _formKey.currentState?.reset();
      });
    }
  }

  // Run validation
  void _validate() {
    setState(() {
      _successMessage = null;
    });

    if (_formKey.currentState!.validate()) {
      setState(() {
        _successMessage = 'Valid! The input passed all checks.';
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    final currentLocale = Localizations.localeOf(context);

    return Scaffold(
      backgroundColor: Colors.grey.shade100,
      appBar: AppBar(
        title: const Text('Best Form Validator'),
        centerTitle: true,
        backgroundColor: Colors.teal,
        foregroundColor: Colors.white,
        actions: [
          PopupMenuButton<String>(
            icon: const Icon(Icons.language),
            onSelected: (langCode) {
              MyApp.of(context)?.setLocale(Locale(langCode));
            },
            itemBuilder: (context) => _languages.entries.map((e) {
              return PopupMenuItem(
                value: e.key,
                child: Text(e.value),
              );
            }).toList(),
          ),
        ],
      ),
      body: Center(
        child: SingleChildScrollView(
          padding: const EdgeInsets.all(24.0),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              Text(
                  'Current Language: ${_languages[currentLocale.languageCode] ?? currentLocale.languageCode}',
                  style: Theme.of(context).textTheme.bodySmall),
              const SizedBox(height: 16),
              const Icon(Icons.verified_user_outlined,
                  size: 64, color: Colors.teal),
              const SizedBox(height: 24),

              // 1. Selection Dropdown
              Text('Select Validator to Test:',
                  style: Theme.of(context)
                      .textTheme
                      .titleMedium
                      ?.copyWith(color: Colors.grey.shade700)),
              const SizedBox(height: 8),
              Container(
                padding: const EdgeInsets.symmetric(horizontal: 16),
                decoration: BoxDecoration(
                  color: Colors.white,
                  borderRadius: BorderRadius.circular(12),
                  border: Border.all(color: Colors.grey.shade300),
                ),
                child: DropdownButtonHideUnderline(
                  child: DropdownButton<String>(
                    value: _selectedCase,
                    isExpanded: true,
                    icon: const Icon(Icons.arrow_drop_down_circle,
                        color: Colors.teal),
                    items: _cases.map((String value) {
                      return DropdownMenuItem<String>(
                        value: value,
                        child: Text(value,
                            style:
                                const TextStyle(fontWeight: FontWeight.w600)),
                      );
                    }).toList(),
                    onChanged: _onCaseChanged,
                  ),
                ),
              ),

              const SizedBox(height: 32),

              // 2. Dynamic Test Area
              Card(
                elevation: 4,
                shadowColor: Colors.black26,
                shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(16)),
                child: Padding(
                  padding: const EdgeInsets.all(24.0),
                  child: Form(
                    key: _formKey,
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.stretch,
                      children: [
                        Text(
                          _selectedCase,
                          style: const TextStyle(
                              fontSize: 20,
                              fontWeight: FontWeight.bold,
                              color: Colors.teal),
                          textAlign: TextAlign.center,
                        ),
                        const SizedBox(height: 8),
                        Text(
                          _getDescription(_selectedCase),
                          style: TextStyle(
                              fontSize: 14, color: Colors.grey.shade600),
                          textAlign: TextAlign.center,
                        ),
                        const SizedBox(height: 24),

                        // Render Input Fields based on selection
                        _buildDynamicFields(),

                        const SizedBox(height: 24),

                        // Submit Button
                        ElevatedButton(
                          onPressed: _validate,
                          style: ElevatedButton.styleFrom(
                            backgroundColor: Colors.teal,
                            foregroundColor: Colors.white,
                            padding: const EdgeInsets.symmetric(vertical: 16),
                            shape: RoundedRectangleBorder(
                                borderRadius: BorderRadius.circular(12)),
                            elevation: 2,
                          ),
                          child: const Row(
                            mainAxisAlignment: MainAxisAlignment.center,
                            children: [
                              Text('VALIDATE CASE',
                                  style: TextStyle(
                                      fontSize: 16,
                                      fontWeight: FontWeight.bold)),
                              SizedBox(width: 8),
                              Icon(Icons.check_circle_outline)
                            ],
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
              ),

              const SizedBox(height: 24),

              // 3. Result Display
              AnimatedOpacity(
                opacity: _successMessage != null ? 1.0 : 0.0,
                duration: const Duration(milliseconds: 300),
                child: _successMessage != null
                    ? Container(
                        padding: const EdgeInsets.all(16),
                        decoration: BoxDecoration(
                          color: Colors.green.shade50,
                          borderRadius: BorderRadius.circular(12),
                          border: Border.all(color: Colors.green),
                        ),
                        child: Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: [
                            const Icon(Icons.check_circle, color: Colors.green),
                            const SizedBox(width: 12),
                            Text(
                              _successMessage!,
                              style: const TextStyle(
                                  color: Colors.green,
                                  fontWeight: FontWeight.bold),
                            ),
                          ],
                        ),
                      )
                    : const SizedBox.shrink(),
              ),
            ],
          ),
        ),
      ),
    );
  }

  // Helper to get description text
  String _getDescription(String caseName) {
    switch (caseName) {
      case 'Email Validation':
        return 'Checks for standard email format requirements.';
      case 'Phone Validation':
        return 'Validates phone numbers against specific country patterns.';
      case 'Password Validation':
        return 'Checks length, special chars, numbers, and letter casing.';
      case 'Name Validation':
        return 'Ensures name contains only letters and appropriate spacing.';
      case 'Age Validation':
        return 'Validates that the age meets a minimum requirement (e.g., 18+).';
      case 'Date Validation':
        return 'Checks if the string is a valid date format.';
      case 'Time Validation':
        return 'Checks if the string is a valid time format.';
      default:
        return '';
    }
  }

  // Builder for dynamic inputs
  Widget _buildDynamicFields() {
    switch (_selectedCase) {
      case 'Email Validation':
        return TextFormField(
          controller: _textController,
          decoration: const InputDecoration(
            labelText: 'Email Address',
            hintText: 'example@domain.com',
            prefixIcon: Icon(Icons.email_outlined),
          ),
          keyboardType: TextInputType.emailAddress,
          validator: (value) => Validators.validateEmail(value),
        );

      case 'Phone Validation':
        return Column(
          children: [
            DropdownButtonFormField<String>(
              key: ValueKey(_selectedCountry),
              initialValue: _selectedCountry,
              decoration: const InputDecoration(
                labelText: 'Select Country',
                prefixIcon: Icon(Icons.flag_outlined),
              ),
              items: _countries
                  .map((c) => DropdownMenuItem(
                        value: c['code'],
                        child: Text(c['name']!),
                      ))
                  .toList(),
              onChanged: (val) => setState(() => _selectedCountry = val!),
            ),
            const SizedBox(height: 16),
            TextFormField(
              controller: _textController,
              decoration: const InputDecoration(
                labelText: 'Phone Number',
                hintText: '+1234567890',
                prefixIcon: Icon(Icons.phone_outlined),
              ),
              keyboardType: TextInputType.phone,
              validator: (value) =>
                  Validators.validatePhone(value, _selectedCountry),
            ),
          ],
        );

      case 'Password Validation':
        return TextFormField(
          controller: _textController,
          obscureText: _obscureText,
          decoration: InputDecoration(
            labelText: 'Password',
            prefixIcon: const Icon(Icons.lock_outline),
            suffixIcon: IconButton(
              icon:
                  Icon(_obscureText ? Icons.visibility_off : Icons.visibility),
              onPressed: () => setState(() => _obscureText = !_obscureText),
            ),
            helperText:
                'Requirements: Min 8 chars, Uppercase, Lowercase, Number, Special Char',
            helperMaxLines: 2,
          ),
          validator: (value) => Validators.validatePassword(
            value,
            minLength: 8,
            checkUpperCase: true,
            checkLowerCase: true,
            checkNumberAndLetter: true,
            checkSpecialCharacter: true,
          ),
        );

      case 'Name Validation':
        return TextFormField(
          controller: _textController,
          decoration: const InputDecoration(
            labelText: 'Full Name',
            hintText: 'John Doe',
            prefixIcon: Icon(Icons.person_outline),
          ),
          keyboardType: TextInputType.name,
          validator: (value) => Validators.validateName(value),
        );

      case 'Age Validation':
        return TextFormField(
          controller: _textController,
          decoration: const InputDecoration(
            labelText: 'Birth Date',
            hintText: 'yyyy-MM-dd',
            prefixIcon: Icon(Icons.cake_outlined),
            helperText: 'Must be at least 18 years old',
          ),
          keyboardType: TextInputType.datetime,
          validator: (value) => Validators.validateAge(value, 18),
        );

      case 'Date Validation':
        return TextFormField(
          controller: _textController,
          decoration: const InputDecoration(
            labelText: 'Date',
            hintText: 'yyyy-MM-dd',
            prefixIcon: Icon(Icons.calendar_today_outlined),
          ),
          keyboardType: TextInputType.datetime,
          validator: (value) => Validators.validateDate(value),
        );

      case 'Time Validation':
        return TextFormField(
          controller: _textController,
          decoration: const InputDecoration(
            labelText: 'Time',
            hintText: 'HH:mm:ss',
            prefixIcon: Icon(Icons.access_time_outlined),
          ),
          keyboardType: TextInputType.datetime,
          validator: (value) => Validators.validateTime(value),
        );

      default:
        return const SizedBox.shrink();
    }
  }
}
7
likes
140
points
107
downloads

Publisher

verified publishergreelogix.com

Weekly Downloads

A comprehensive Flutter package for form validation with support for email, phone (50+ countries), password, name, age, date, time validation, and full localization support. Customizable error messages and null-safe.

Repository (GitHub)
View/report issues

Topics

#form #validator #email #phone #password

Documentation

Documentation
API reference

License

unknown (license)

Dependencies

flutter, flutter_localizations, intl

More

Packages that depend on best_form_validator