skills/flutter/references/features-forms-validation.md

4.8 KiB

name description
features-forms-validation Flutter form validation - Form, FormField, validators, and form handling patterns

Form Validation

Flutter provides comprehensive form validation capabilities.

Basic Form

final _formKey = GlobalKey<FormState>();

Form(
  key: _formKey,
  child: Column(
    children: [
      TextFormField(
        decoration: const InputDecoration(labelText: 'Email'),
        validator: (value) {
          if (value == null || value.isEmpty) {
            return 'Please enter email';
          }
          return null;
        },
      ),
      ElevatedButton(
        onPressed: () {
          if (_formKey.currentState!.validate()) {
            // Form is valid
          }
        },
        child: const Text('Submit'),
      ),
    ],
  ),
)

Email Validation

TextFormField(
  decoration: const InputDecoration(labelText: 'Email'),
  keyboardType: TextInputType.emailAddress,
  validator: (value) {
    if (value == null || value.isEmpty) {
      return 'Please enter email';
    }
    if (!RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$').hasMatch(value)) {
      return 'Please enter valid email';
    }
    return null;
  },
)

Password Validation

TextFormField(
  decoration: const InputDecoration(labelText: 'Password'),
  obscureText: true,
  validator: (value) {
    if (value == null || value.isEmpty) {
      return 'Please enter password';
    }
    if (value.length < 8) {
      return 'Password must be at least 8 characters';
    }
    if (!RegExp(r'[A-Z]').hasMatch(value)) {
      return 'Password must contain uppercase letter';
    }
    if (!RegExp(r'[0-9]').hasMatch(value)) {
      return 'Password must contain number';
    }
    return null;
  },
)

Custom Validator

String? validatePhone(String? value) {
  if (value == null || value.isEmpty) {
    return 'Please enter phone number';
  }
  if (!RegExp(r'^\+?[1-9]\d{1,14}$').hasMatch(value)) {
    return 'Please enter valid phone number';
  }
  return null;
}

// Usage
TextFormField(
  decoration: const InputDecoration(labelText: 'Phone'),
  validator: validatePhone,
)

FormField

Custom form field with validation.

FormField<String>(
  validator: (value) {
    if (value == null || value.isEmpty) {
      return 'Please enter value';
    }
    return null;
  },
  builder: (field) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        TextField(
          onChanged: field.didChange,
          decoration: InputDecoration(
            labelText: 'Custom Field',
            errorText: field.errorText,
          ),
        ),
      ],
    );
  },
)

Autovalidate Mode

Form(
  autovalidateMode: AutovalidateMode.onUserInteraction,
  child: TextFormField(
    validator: (value) {
      if (value == null || value.isEmpty) {
        return 'Required';
      }
      return null;
    },
  ),
)

Form State

final _formKey = GlobalKey<FormState>();

// Validate form
if (_formKey.currentState!.validate()) {
  // Form is valid
}

// Save form
_formKey.currentState!.save();

// Reset form
_formKey.currentState!.reset();

Multiple Fields

final _formKey = GlobalKey<FormState>();
final _emailController = TextEditingController();
final _passwordController = TextEditingController();

Form(
  key: _formKey,
  child: Column(
    children: [
      TextFormField(
        controller: _emailController,
        decoration: const InputDecoration(labelText: 'Email'),
        validator: (value) {
          if (value == null || value.isEmpty) {
            return 'Required';
          }
          return null;
        },
      ),
      TextFormField(
        controller: _passwordController,
        decoration: const InputDecoration(labelText: 'Password'),
        obscureText: true,
        validator: (value) {
          if (value == null || value.isEmpty) {
            return 'Required';
          }
          return null;
        },
      ),
      ElevatedButton(
        onPressed: () {
          if (_formKey.currentState!.validate()) {
            final email = _emailController.text;
            final password = _passwordController.text;
            // Process form
          }
        },
        child: const Text('Submit'),
      ),
    ],
  ),
)

Key Points

  • Use Form widget to wrap form fields
  • Use GlobalKey<FormState> to access form state
  • Use validator function for field validation
  • Return null for valid values, error string for invalid
  • Use validate() to check form validity
  • Use save() to save form values
  • Use reset() to reset form
  • Set autovalidateMode for real-time validation
  • Use regex patterns for complex validation