From flutter-skills
Builds Flutter forms with validation and user input handling. Use when creating login screens, data entry forms, or any multi-field user input.
npx claudepluginhub gsmlg-dev/code-agent --plugin flutter-skillsThis skill uses the workspace's default tool permissions.
- [Form Architecture](#form-architecture)
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Searches prompts.chat for AI prompt templates by keyword or category, retrieves by ID with variable handling, and improves prompts via AI. Use for discovering or enhancing prompts.
Guides MCP server integration in Claude Code plugins via .mcp.json or plugin.json configs for stdio, SSE, HTTP types, enabling external services as tools.
Implement forms using a Form widget to group and validate multiple input fields together.
Form inside a StatefulWidget.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.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.Form.of(context) to access the FormState from a descendant widget.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.
validator() callback function to each TextFormField.String containing the specific error message. The Form will automatically rebuild to display this text below the field.null.Follow this sequential workflow to implement and validate a form. Copy the checklist to track your progress.
Task Progress:
StatefulWidget and its corresponding State class.final _formKey = GlobalKey<FormState>(); in the State class.Form widget in the build method and assign key: _formKey.TextFormField widgets as descendants of the Form.validator function for each TextFormField (return String on error, null on success).ElevatedButton).onPressed callback using _formKey.currentState!.validate().When the user triggers the submit action, execute the following conditional logic:
_formKey.currentState!.validate().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).false (Invalid): One or more validators returned an error string. The FormState automatically rebuilds the UI to display the error messages.validate() returns true.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'),
),
],
),
);
}
}