0
0
Fluttermobile~20 mins

Form widget and GlobalKey in Flutter - Mini App: Build & Ship

Choose your learning style9 modes available
Build: Simple Login Form
A login screen with a form that validates user input using a GlobalKey.
Target UI
-------------------------
| Simple Login Form      |
|-----------------------|
| Email: [___________]  |
| Password: [_______]   |
|                       |
|       [Login]         |
-------------------------
Use a Form widget with a GlobalKey to manage form state.
Include two TextFormFields: one for email and one for password.
Validate email to check if it contains '@' and is not empty.
Validate password to ensure it is at least 6 characters.
Add a Login button that triggers validation and shows a SnackBar on success.
Starter Code
Flutter
import 'package:flutter/material.dart';

class LoginFormScreen extends StatefulWidget {
  @override
  State<LoginFormScreen> createState() => _LoginFormScreenState();
}

class _LoginFormScreenState extends State<LoginFormScreen> {
  final _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Simple Login Form')),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Form(
          key: _formKey,
          child: Column(
            children: [
              // TODO: Add email TextFormField here
              // TODO: Add password TextFormField here
              SizedBox(height: 20),
              ElevatedButton(
                onPressed: () {
                  // TODO: Add form validation and SnackBar here
                },
                child: Text('Login'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
Task 1
Task 2
Task 3
Task 4
Solution
Flutter
import 'package:flutter/material.dart';

class LoginFormScreen extends StatefulWidget {
  @override
  State<LoginFormScreen> createState() => _LoginFormScreenState();
}

class _LoginFormScreenState extends State<LoginFormScreen> {
  final _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Simple Login Form')),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Form(
          key: _formKey,
          child: Column(
            children: [
              TextFormField(
                decoration: InputDecoration(labelText: 'Email'),
                keyboardType: TextInputType.emailAddress,
                validator: (value) {
                  if (value == null || value.isEmpty) {
                    return 'Please enter your email';
                  }
                  if (!value.contains('@')) {
                    return 'Enter a valid email';
                  }
                  return null;
                },
              ),
              TextFormField(
                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';
                  }
                  return null;
                },
              ),
              SizedBox(height: 20),
              ElevatedButton(
                onPressed: () {
                  if (_formKey.currentState?.validate() ?? false) {
                    ScaffoldMessenger.of(context).showSnackBar(
                      SnackBar(content: Text('Login Successful!')),
                    );
                  }
                },
                child: Text('Login'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

This screen uses a Form widget with a GlobalKey to manage the form state. The TextFormField widgets each have a validator function that checks the input. The email field checks if the input is not empty and contains an '@' symbol. The password field checks if the input is not empty and has at least 6 characters.

When the Login button is pressed, the form is validated by calling _formKey.currentState?.validate(). If all validators return null (meaning valid), a SnackBar appears with a success message. This approach keeps validation logic clean and user feedback immediate.

Final Result
Completed Screen
-------------------------
| Simple Login Form      |
|-----------------------|
| Email: [user@example] |
| Password: [******]    |
|                       |
|       [Login]         |
-------------------------
User types email and password in the fields.
User taps Login button.
If inputs are invalid, error messages appear below fields.
If inputs are valid, a SnackBar shows 'Login Successful!'.
Stretch Goal
Add a 'Show Password' checkbox that toggles password visibility.
💡 Hint
Use a boolean state variable to control the obscureText property of the password TextFormField.