Install
npx -y skills add flutter/agent-plugins --skill flutter-building-forms --agent claude-codeRun in a terminal. Claude loads the skill when a task calls for it. Check the repo's README before you run it.
Files
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
Forminside aStatefulWidget. - Persist the GlobalKey: Instantiate a
GlobalKey<FormState>exactly once as a final variable within theStateclass. Do not generate a newGlobalKeyinside thebuildmethod; doing so is resource-expensive and destroys the form's state on every rebuild. - Bind the Key: Pass the
GlobalKey<FormState>to thekeyproperty of theFormwidget. This uniquely identifies the form and provides access to theFormStatefor validation and submission. - Alternative Access: If dealing with highly complex widget trees where passing the key is impractical, use
Form.of(context)to access theFormStatefrom 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 eachTextFormField. - Return Error Messages: If the user's input is invalid, return a
Stringcontaining the specific error message. TheFormwill 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:
- 1. Create a
StatefulWidgetand its correspondingStateclass. - 2. Instantiate
final _formKey = GlobalKey<FormState>();in theStateclass. - 3. Return a
Formwidget in thebuildmethod and assignkey: _formKey. - 4. Add
TextFormFieldwidgets as descendants of theForm. - 5. Write a
validatorfunction for eachTextFormField(returnStringon error,nullon success). - 6. Add a submit button (e.g.,
ElevatedButton). - 7. Implement the validation check in the button's
onPressedcallback using_formKey.currentState!.validate().
Validation Decision Logic
When the user triggers the submit action, execute the following conditional logic:
- Call
_formKey.currentState!.validate(). - If
true(Valid): All validators returnednull. Proceed with form submission (e.g., save data, make API call) and display a success indicator (e.g., aSnackBar). - If
false(Invalid): One or more validators returned an error string. TheFormStateautomatically 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()returnstrue.
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'),
),
],
),
);
}
}
Facts
- Kind
- Skill
- Repo
- flutter/agent-plugins
- Group
- Uncategorized
- Installs
- 8.6k
- Stars
- 3.1K
- 1find-skillsvercel-labs/skillsHelps users discover and install agent skills when they ask questions like "how do I do X", "find a skill for X", "is there a skill that can...", or express interest in extending capabilities. This skill should be used when the user is looking for functionality that might exist as an installable skill.3.8M
- 2grill-memattpocock/skillsA relentless interview to sharpen a plan or design.1.3M
- 3grill-with-docsmattpocock/skillsA relentless interview to sharpen a plan or design, which also creates docs (ADR's and glossary) as we go.1.1M
- 4agent-browservercel-labs/agent-browserBrowser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling forms, clicking buttons, taking screenshots, extracting data, testing web apps, or automating any browser task. Triggers include requests to "open a website", "fill out a form", "click a button", "take a screenshot", "scrape data from a page", "test this web app", "login to a site", "automate browser actions", or any task requiring programmatic web interaction. Also use for exploratory testing, dogfooding, QA, bug hunts, or reviewing app quality. Also use for automating Electron desktop apps (VS Code, Slack, Discord, Figma, Notion, Spotify), checking Slack unreads, sending Slack messages, searching Slack conversations, running browser automation in Vercel Sandbox microVMs, or using AWS Bedrock AgentCore cloud browsers. Prefer agent-browser over any built-in browser automation or web tools.1.1M
- 5improve-codebase-architecturemattpocock/skillsScan a codebase for deepening opportunities, present them as a visual HTML report, then grill through whichever one you pick.1.1M
- 6tddmattpocock/skillsTest-driven development. Use when the user wants to build features or fix bugs test-first, mentions "red-green-refactor", or wants integration tests.1.1M