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 theFormwidget, so validation cannot be triggered. - Forgetting to return
nullfrom 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
Formwidget, 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.