# Form Handling

practisingHandling forms correctly is crucial for a good user experience. Flutter provides various widgets and techniques to validate and manage form data.

## 1. `Form` and `FormField` Widgets 📋

The `Form` widget acts as a container for grouping and validating multiple form fields. `FormField` is a single form field.

```dart
Form(
  key: _formKey,
  child: Column(
    children: <Widget>[
      TextFormField(
        validator: (value) {
          if (value == null || value.isEmpty) {
            return 'Please enter some text';
          }
          return null;
        },
      ),
      ElevatedButton(
        onPressed: () {
          if (_formKey.currentState?.validate() ?? false) {
            // If the form is valid, display a Snackbar
            ScaffoldMessenger.of(context)
                .showSnackBar(SnackBar(content: Text('Processing Data')));
          }
        },
        child: Text('Submit'),
      )
    ],
  ),
)
```

## 2. Validation 🛂

Validation is performed by providing a `validator` function to the `FormField`.

```dart
TextFormField(
  validator: (value) {
    if (value == null || value.isEmpty) {
      return 'Please enter some text';
    }
    return null;
  },
)
```

## 3. Saving Form Data 💾

You can save form data by providing a `onSaved` callback to the `FormField`.

```dart
TextFormField(
  onSaved: (value) {
    // Save value
  },
)
```

## 4. Accessing Form Data 🗂️

Access the form data using a `GlobalKey` to access the `Form` state and then call `save` on it.

```dart
final _formKey = GlobalKey<FormState>();

// To save
_formKey.currentState?.save();
```

## 5. Focus and Text Controllers 🎯

Manage focus and text input using `FocusNode` and `TextEditingController`.

```dart
final myController = TextEditingController();

// Use in a TextField
TextField(
  controller: myController,
)
```

## Complete Code & Result

{% tabs %}
{% tab title="Code" %}

```dart
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: FormExample(),
    );
  }
}

class FormExample extends StatefulWidget {
  @override
  _FormExampleState createState() => _FormExampleState();
}

class _FormExampleState extends State<FormExample> {
  final _formKey = GlobalKey<FormState>();
  final _nameController = TextEditingController();
  final _emailController = TextEditingController();
  final _passwordController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Form Handling Example'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Form(
          key: _formKey,
          child: Column(
            children: <Widget>[
              TextFormField(
                controller: _nameController,
                decoration: InputDecoration(labelText: 'Name'),
                validator: (value) {
                  if (value == null || value.isEmpty) {
                    return 'Please enter your name';
                  }
                  return null;
                },
              ),
              TextFormField(
                controller: _emailController,
                decoration: InputDecoration(labelText: 'Email'),
                validator: (value) {
                  if (value == null || value.isEmpty) {
                    return 'Please enter your email';
                  }
                  // Basic email validation
                  if (!RegExp(r"^[a-zA-Z0-9.]+@[a-zA-Z0-9]+\.[a-zA-Z]+").hasMatch(value)) {
                    return 'Please enter a valid email address';
                  }
                  return null;
                },
              ),
              TextFormField(
                controller: _passwordController,
                decoration: InputDecoration(labelText: 'Password'),
                obscureText: true,
                validator: (value) {
                  if (value == null || value.isEmpty) {
                    return 'Please enter your password';
                  }
                  if (value.length < 6) {
                    return 'Password must be at least 6 characters long';
                  }
                  return null;
                },
              ),
              SizedBox(height: 20),
              ElevatedButton(
                onPressed: () {
                  if (_formKey.currentState?.validate() ?? false) {
                    // If the form is valid, navigate to a new screen and display the user data
                    Navigator.push(
                      context,
                      MaterialPageRoute(
                        builder: (context) => UserDataScreen(
                          name: _nameController.text,
                          email: _emailController.text,
                          password: _passwordController.text,
                        ),
                      ),
                    );
                  }
                },
                child: Text('Submit'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class UserDataScreen extends StatelessWidget {
  final String name;
  final String email;
  final String password;

  UserDataScreen({required this.name, required this.email, required this.password});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('User Data'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            Text('Name: $name'),
            Text('Email: $email'),
            Text('Password: $password'),
          ],
        ),
      ),
    );
  }
}

```

{% endtab %}

{% tab title="Result" %}

<figure><img src="https://522858097-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOdSyMra5vx5HbARBPAir%2Fuploads%2FHMEJOOMOFWnsgxj02DWL%2Fezgif.com-video-to-gif%20(5).gif?alt=media&#x26;token=249938b6-78f4-4171-af4e-31a1007dbe56" alt="" width="450"><figcaption></figcaption></figure>
{% endtab %}
{% endtabs %}

## Assignments 📝

Practice makes perfect! Here are some exercises:

* [ ] Create a form with at least three fields (e.g., name, email, password) and validate the input.
* [ ] Save the data from the form and display it in a new screen.
* [ ] Create a form with some fields that have initial values.
* [ ] Manage focus between text fields using a `FocusNode`.

{% hint style="info" %}
By understanding and practising form handling in Flutter, you’ll be well-equipped to create robust and user-friendly forms in your apps.
{% endhint %}

Next, delve into Networking to learn how to interact with external data sources!


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://flutteruniversity.gitbook.io/docs/learn-flutter/intermediate/form-handling.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
