# 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!
