---
name: "flutter-building-forms"
description: "Builds Flutter forms with validation and user input handling. Use when creating login screens, data entry forms, or any multi-field user input."
metadata:
  model: "models/gemini-3.1-pro-preview"
  last_modified: "Thu, 12 Mar 2026 22:15:24 GMT"

---
# Building Validated Forms

## Contents
- [Form Architecture](#form-architecture)
- [Field Validation](#field-validation)
- [Workflow: Implementing a Validated Form](#workflow-implementing-a-validated-form)
- [Examples](#examples)

## 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:**
- [ ] 1. Create a `StatefulWidget` and its corresponding `State` class.
- [ ] 2. Instantiate `final _formKey = GlobalKey<FormState>();` in the `State` class.
- [ ] 3. Return a `Form` widget in the `build` method and assign `key: _formKey`.
- [ ] 4. Add `TextFormField` widgets as descendants of the `Form`.
- [ ] 5. Write a `validator` function for each `TextFormField` (return `String` on error, `null` on success).
- [ ] 6. Add a submit button (e.g., `ElevatedButton`).
- [ ] 7. Implement the validation check in the button's `onPressed` callback using `_formKey.currentState!.validate()`.

### Validation Decision Logic

When the user triggers the submit action, execute the following conditional logic:

1. Call `_formKey.currentState!.validate()`.
2. **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`).
3. **If `false` (Invalid):** One or more validators returned an error string. The `FormState` automatically rebuilds the UI to display the error messages. 
4. **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.

```dart
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 attribution: dangdungvn
Original project: https://github.com/dangdungvn/review_system_app/blob/f397d2abe0a8d4c041cd274f0ffc5680d85e7c44/.github/skills/flutter-building-forms/SKILL.md
License: MIT
License information: https://opensource.org/license/mit
Original upstream instructions; downloaded from Dave AI.

## Upstream license notice

MIT License

Copyright (c) 2024 Minh Nguyen

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.



# Dave AI resource metadata

Creator / publisher: dangdungvn
Original project: https://github.com/dangdungvn/review_system_app/blob/f397d2abe0a8d4c041cd274f0ffc5680d85e7c44/.github/skills/flutter-building-forms/SKILL.md
Attribution basis: Source repository record

Fields of work: Development & Engineering
Roles: Frontend Developer, Mobile Developer
Specialties: Frontend, Mobile
Tools: Tool not specified
Country applicability: Country not specified
Classification basis: Source catalog labels
Instruction SHA-256: 648df65d2d6552edb8591404fc4bdaacf29f2984a5ed444b7978c86e80530e38
