0
0
FlutterHow-ToBeginner · 4 min read

How to Validate Form in Flutter: Simple Guide with Example

In Flutter, you validate a form by wrapping input fields inside a Form widget and using TextFormField with a validator function. Call FormState.validate() to check all fields and show error messages if inputs are invalid.
📐

Syntax

Use a Form widget with a GlobalKey<FormState> to manage form state. Inside the form, use TextFormField widgets with a validator callback that returns an error string if input is invalid or null if valid. Call _formKey.currentState!.validate() to trigger validation.

dart
final _formKey = GlobalKey<FormState>();

Form(
  key: _formKey,
  child: Column(
    children: [
      TextFormField(
        validator: (value) {
          if (value == null || value.isEmpty) {
            return 'Please enter some text';
          }
          return null;
        },
      ),
      ElevatedButton(
        onPressed: () {
          if (_formKey.currentState!.validate()) {
            // Process data
          }
        },
        child: Text('Submit'),
      ),
    ],
  ),
);
💻

Example

This example shows a simple form with one text field that requires input. When the user taps Submit, the form validates the input and shows an error message if the field is empty.

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

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Form Validation Example')),
        body: Padding(
          padding: EdgeInsets.all(16),
          child: MyCustomForm(),
        ),
      ),
    );
  }
}

class MyCustomForm extends StatefulWidget {
  @override
  _MyCustomFormState createState() => _MyCustomFormState();
}

class _MyCustomFormState extends State<MyCustomForm> {
  final _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    return Form(
      key: _formKey,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          TextFormField(
            decoration: InputDecoration(labelText: 'Enter your name'),
            validator: (value) {
              if (value == null || value.isEmpty) {
                return 'Please enter your name';
              }
              return null;
            },
          ),
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 16.0),
            child: ElevatedButton(
              onPressed: () {
                if (_formKey.currentState!.validate()) {
                  ScaffoldMessenger.of(context).showSnackBar(
                    SnackBar(content: Text('Processing Data')),
                  );
                }
              },
              child: Text('Submit'),
            ),
          ),
        ],
      ),
    );
  }
}
Output
A screen with a text field labeled 'Enter your name' and a Submit button. If the field is empty and Submit is tapped, an error message 'Please enter your name' appears below the field. If valid, a snackbar with 'Processing Data' shows.
⚠️

Common Pitfalls

  • Not assigning a GlobalKey<FormState> to the Form widget, so validation cannot be triggered.
  • Forgetting to return null from the validator when input is valid, causing the field to always show an error.
  • Calling validate() without checking if the form key is attached, which can cause runtime errors.
  • Not wrapping input fields inside a Form widget, so validation methods are unavailable.
dart
/* Wrong: No Form key and no Form widget */
TextFormField(
  validator: (value) => value!.isEmpty ? 'Required' : null,
),

/* Right: Use Form with GlobalKey and validate() */
final _formKey = GlobalKey<FormState>();

Form(
  key: _formKey,
  child: TextFormField(
    validator: (value) => value!.isEmpty ? 'Required' : null,
  ),
);
📊

Quick Reference

  • Form widget: Wraps input fields to manage validation state.
  • GlobalKey<FormState>: Used to access form methods like validate().
  • TextFormField validator: Returns error string or null.
  • validate(): Checks all validators and returns true if all valid.
  • Show errors: Validator error messages appear below fields automatically.

Key Takeaways

Wrap input fields inside a Form widget with a GlobalKey to manage validation.
Use TextFormField's validator callback to check input and return error messages.
Call _formKey.currentState!.validate() to trigger validation and get a boolean result.
Return null from validator when input is valid to hide error messages.
Always check that the form key is attached before calling validate to avoid errors.