0
0
Fluttermobile~20 mins

Why validation ensures data quality in Flutter - Build It to Prove It

Choose your learning style9 modes available
Build: User Registration
This screen collects user information and uses validation to ensure the data entered is correct and complete before submission.
Target UI
-------------------------
| User Registration     |
|-----------------------|
| Name: [___________]   |
| Email: [___________]  |
| Password: [_______]   |
|                       |
| [Submit]              |
-------------------------
Add TextFields for Name, Email, and Password.
Validate that Name is not empty.
Validate Email format contains '@' and '.' characters.
Validate Password is at least 6 characters.
Show error messages below each field if validation fails.
Disable Submit button if any validation fails.
Show a success message when all data is valid and Submit is pressed.
Starter Code
Flutter
import 'package:flutter/material.dart';

class UserRegistration extends StatefulWidget {
  @override
  State<UserRegistration> createState() => _UserRegistrationState();
}

class _UserRegistrationState extends State<UserRegistration> {
  final _formKey = GlobalKey<FormState>();

  // TODO: Add TextEditingControllers for name, email, password

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('User Registration')),
      body: Padding(
        padding: EdgeInsets.all(16),
        child: Form(
          key: _formKey,
          child: Column(
            children: [
              // TODO: Add TextFormFields for Name, Email, Password with validators
              SizedBox(height: 20),
              ElevatedButton(
                onPressed: () {
                  // TODO: Validate form and show success message
                },
                child: Text('Submit'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
Task 1
Task 2
Task 3
Task 4
Task 5
Solution
Flutter
import 'package:flutter/material.dart';

class UserRegistration extends StatefulWidget {
  @override
  State<UserRegistration> createState() => _UserRegistrationState();
}

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

  bool _autoValidate = false;

  bool get _isFormValid {
    return _formKey.currentState?.validate() ?? false;
  }

  void _submit() {
    setState(() {
      _autoValidate = true;
    });
    if (_formKey.currentState?.validate() ?? false) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Registration Successful!')),
      );
    }
  }

  @override
  void dispose() {
    _nameController.dispose();
    _emailController.dispose();
    _passwordController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('User Registration')),
      body: Padding(
        padding: EdgeInsets.all(16),
        child: Form(
          key: _formKey,
          autovalidateMode: _autoValidate ? AutovalidateMode.always : AutovalidateMode.disabled,
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              TextFormField(
                controller: _nameController,
                decoration: InputDecoration(labelText: 'Name'),
                validator: (value) {
                  if (value == null || value.trim().isEmpty) {
                    return 'Name cannot be empty';
                  }
                  return null;
                },
              ),
              SizedBox(height: 12),
              TextFormField(
                controller: _emailController,
                decoration: InputDecoration(labelText: 'Email'),
                keyboardType: TextInputType.emailAddress,
                validator: (value) {
                  if (value == null || value.trim().isEmpty) {
                    return 'Email cannot be empty';
                  }
                  if (!value.contains('@') || !value.contains('.')) {
                    return 'Enter a valid email';
                  }
                  return null;
                },
              ),
              SizedBox(height: 12),
              TextFormField(
                controller: _passwordController,
                decoration: InputDecoration(labelText: 'Password'),
                obscureText: true,
                validator: (value) {
                  if (value == null || value.length < 6) {
                    return 'Password must be at least 6 characters';
                  }
                  return null;
                },
              ),
              SizedBox(height: 24),
              SizedBox(
                width: double.infinity,
                child: ElevatedButton(
                  onPressed: _isFormValid ? _submit : null,
                  child: Text('Submit'),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

This screen uses a Form widget with TextFormFields for Name, Email, and Password. Each field has a validator function that checks the input:

  • Name must not be empty.
  • Email must contain '@' and '.' to be considered valid.
  • Password must be at least 6 characters long.

The Submit button is disabled if the form is invalid, preventing bad data submission. When the user presses Submit, the form validates again and shows a success message if all data is good.

This validation ensures the app only accepts quality data, avoiding errors later and improving user experience.

Final Result
Completed Screen
-------------------------
| User Registration     |
|-----------------------|
| Name: [John Doe    ]  |
| Email: [john@mail.com]|
| Password: [******   ] |
|                       |
| [Submit]              |
-------------------------
If any field is empty or invalid, an error message appears below it.
Submit button is disabled until all fields are valid.
Pressing Submit with valid data shows a success message at the bottom.
Stretch Goal
Add a toggle to show or hide the password text.
💡 Hint
Use a boolean state variable to switch obscureText property of the password TextFormField and add an IconButton inside the field's suffixIcon.