Flutter Form Validation: solved exercise
If you are looking for Flutter form validation, this solved exercise gives you a practical implementation pattern you can reuse in real projects.
Problem statement
Build a screen with:
- email field
- password field
- field validation rules
- submit button with user feedback
Flutter solution
import 'package:flutter/material.dart';
void main() => runApp(const MaterialApp(home: LoginFormPage()));
class LoginFormPage extends StatefulWidget {
const LoginFormPage({super.key});
@override
State<LoginFormPage> createState() => _LoginFormPageState();
}
class _LoginFormPageState extends State<LoginFormPage> {
final _formKey = GlobalKey<FormState>();
final _emailCtrl = TextEditingController();
final _passCtrl = TextEditingController();
@override
void dispose() {
_emailCtrl.dispose();
_passCtrl.dispose();
super.dispose();
}
void submit() {
if (_formKey.currentState!.validate()) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Formulario valido: ${_emailCtrl.text}')),
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Formulario Flutter')),
body: Padding(
padding: const EdgeInsets.all(16),
child: Form(
key: _formKey,
child: Column(
children: [
TextFormField(
controller: _emailCtrl,
decoration: const InputDecoration(labelText: 'Email'),
validator: (value) {
if (value == null || value.isEmpty) return 'Email obligatorio';
if (!value.contains('@')) return 'Email no valido';
return null;
},
),
TextFormField(
controller: _passCtrl,
decoration: const InputDecoration(labelText: 'Password'),
obscureText: true,
validator: (value) {
if (value == null || value.length < 6) return 'Minimo 6 caracteres';
return null;
},
),
const SizedBox(height: 16),
ElevatedButton(onPressed: submit, child: const Text('Enviar')),
],
),
),
),
);
}
}Expected result
The form submits only when all validation rules are satisfied.
Common mistakes
- Not using
GlobalKey<FormState>. - Triggering validation on every keystroke without strategy.
- Forgetting to dispose controllers.
Practical use
This pattern is the base for login, signup, checkout, and internal business forms.
Recommended next exercise
- BottomNavigationBar in Flutter: solved exercise with IndexedStack
- Flutter Counter with setState: solved exercise step by step
- ListView.builder in Flutter: solved exercise with dynamic list
- All Flutter exercises
Guided practice and next step
- More Flutter exercises
- C exercises to strengthen fundamentals
- Programming in C in 100 Solved Exercises
- View the C book on Amazon (included in Kindle Unlimited)
- Subscribe to the newsletter
FAQ
Which widgets are standard for forms in Flutter?
Form with TextFormField and per-field validators.
Where should validation errors live?
Inside field validators with clear and short messages.
Does this scale to bigger forms?
Yes. Extract validators and field widgets as the screen grows.