How do you implement form validation in Flutter?
Short Answer
Wrap your fields in a Form widget with a GlobalKey<FormState>, give each TextFormField a validator function, and call formKey.currentState!.validate() to trigger all validators at once.
The Form widget acts as a container that can validate, save, and reset all of its descendant FormFields (like TextFormField) together. You attach a GlobalKey<FormState> to the Form so you can imperatively call methods on it — most importantly validate(), which runs every field's validator callback and returns true only if all of them return null (no error).
Each TextFormField's validator takes the current value and returns either an error string (shown under the field) or null (valid). onSaved callbacks let you collect all field values in one formKey.currentState!.save() call, convenient for building a data object from many fields at once.
Code Example
final _formKey = GlobalKey<FormState>();
Form(
key: _formKey,
child: Column(
children: [
TextFormField(
validator: (value) {
if (value == null || value.isEmpty) return 'Required';
if (!value.contains('@')) return 'Enter a valid email';
return null;
},
),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
// all fields valid
}
},
child: const Text('Submit'),
),
],
),
)Common Mistakes
- ×Forgetting to wrap fields in a Form widget — validator only runs when Form.validate() is called.
- ×Not calling setState() or using autovalidateMode when error messages should update live as the user types.