| name | flutter-building-forms |
| description | Build Flutter forms with validation and input handling. Use for login screens, data entry, multi-field input. Use when this capability is needed. |
| metadata | {"author":"build-with-dhiraj"} |
Building Validated Forms
Contents
Form Architecture
Implement forms using a Form widget to group and validate multiple input fields together.
- Use a StatefulWidget: Always host your
Form inside a StatefulWidget.
- Persist the GlobalKey: Instantiate a
GlobalKey<FormState> exactly once as a final variable within the State class. Do not generate a new GlobalKey inside the build method; doing so is resource-expensive and destroys the form's state on every rebuild.
- Bind the Key: Pass the
GlobalKey<FormState> to the key property of the Form widget. This uniquely identifies the form and provides access to the FormState for validation and submission.
- Alternative Access: If dealing with highly complex widget trees where passing the key is impractical, use
Form.of(context) to access the FormState from a descendant widget.
Field Validation
Use TextFormField to render Material Design text inputs with built-in validation support. TextFormField is a convenience widget that automatically wraps a standard TextField inside a FormField.
- Implement the Validator: Provide a
validator() callback function to each TextFormField.
- Return Error Messages: If the user's input is invalid, return a
String containing the specific error message. The Form will automatically rebuild to display this text below the field.
- Return Null for Success: If the input passes validation, you must return
null.
Workflow: Implementing a Validated Form
Follow this sequential workflow to implement and validate a form. Copy the checklist to track your progress.
Task Progress:
Validation Decision Logic
When the user triggers the submit action, execute the following conditional logic:
- Call
_formKey.currentState!.validate().
- If
true (Valid): All validators returned null. Proceed with form submission (e.g., save data, make API call) and display a success indicator (e.g., a SnackBar).
- If
false (Invalid): One or more validators returned an error string. The FormState automatically rebuilds the UI to display the error messages.
- Feedback Loop: Run validator -> review errors -> fix. The user must adjust their input and resubmit until
validate() returns true.
Examples
Complete Validated Form Implementation
Use the following pattern to implement a robust, validated form.
import 'package:flutter/material.dart';
class UserRegistrationForm extends StatefulWidget {
const UserRegistrationForm({super.key});
@override
State<UserRegistrationForm> createState() => _UserRegistrationFormState();
}
class _UserRegistrationFormState extends State<UserRegistrationForm> {
// 1. Persist the GlobalKey in the State class
final _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
// 2. Bind the key to the Form
return Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 3. Add TextFormFields with validators
TextFormField(
decoration: const InputDecoration(
labelText: 'Username',
hintText: 'Enter your username',
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter a username'; // Error state
}
if (value.length < 4) {
return 'Username must be at least 4 characters'; // Error state
}
return null; // Valid state
},
),
const SizedBox(height: 16),
// 4. Add the submit button
ElevatedButton(
onPressed: () {
// 5. Trigger validation logic
if (_formKey.currentState!.validate()) {
// Form is valid: Process data
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Processing Data')),
);
} else {
// Form is invalid: Errors are automatically displayed
debugPrint('Form validation failed.');
}
},
child: const Text('Submit'),
),
],
),
);
}
}
Source: build-with-dhiraj/ai-workflow-framework-portability-kit — distributed by TomeVault.