Bird
Raised Fist0
Fluttermobile~20 mins

Form validation rules in Flutter - Mini App: Build & Ship

Choose your learning style10 modes available
Build: Simple Form Validation
A screen with a form that validates user input for email and password fields. It shows error messages if inputs are invalid and a success message when the form is submitted correctly.
Target UI
-------------------------
| Simple Form Validation |
-------------------------
| Email:                |
| [____________________]|
| (error message here)  |
| Password:             |
| [____________________]|
| (error message here)  |
|                       |
| [ Submit ]            |
-------------------------
Two TextFormFields: one for email, one for password
Email field must check for valid email format
Password field must check for minimum 6 characters
Show error messages below each field if invalid
Submit button validates the form and shows a SnackBar with success message if valid
Starter Code
Flutter
import 'package:flutter/material.dart';

class SimpleFormValidation extends StatefulWidget {
  @override
  State<SimpleFormValidation> createState() => _SimpleFormValidationState();
}

class _SimpleFormValidationState extends State<SimpleFormValidation> {
  final _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Simple Form Validation')),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Form(
          key: _formKey,
          child: Column(
            children: [
              // TODO: Add Email TextFormField with validation
              // TODO: Add Password TextFormField with validation
              // TODO: Add Submit ElevatedButton
            ],
          ),
        ),
      ),
    );
  }
}
Task 1
Task 2
Task 3
Solution
Flutter
import 'package:flutter/material.dart';

class SimpleFormValidation extends StatefulWidget {
  @override
  State<SimpleFormValidation> createState() => _SimpleFormValidationState();
}

class _SimpleFormValidationState extends State<SimpleFormValidation> {
  final _formKey = GlobalKey<FormState>();
  final _emailController = TextEditingController();
  final _passwordController = TextEditingController();

  String? _validateEmail(String? value) {
    if (value == null || value.isEmpty) {
      return 'Please enter your email';
    }
    final emailRegex = RegExp(r'^[\w-.]+@[\w-]+\.[a-z]{2,}$', caseSensitive: false);
    if (!emailRegex.hasMatch(value)) {
      return 'Enter a valid email address';
    }
    return null;
  }

  String? _validatePassword(String? 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;
  }

  void _submit() {
    if (_formKey.currentState?.validate() ?? false) {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('Form submitted successfully!')),
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Simple Form Validation')),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Form(
          key: _formKey,
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              TextFormField(
                controller: _emailController,
                decoration: const InputDecoration(
                  labelText: 'Email',
                  border: OutlineInputBorder(),
                ),
                keyboardType: TextInputType.emailAddress,
                validator: _validateEmail,
              ),
              const SizedBox(height: 12),
              TextFormField(
                controller: _passwordController,
                decoration: const InputDecoration(
                  labelText: 'Password',
                  border: OutlineInputBorder(),
                ),
                obscureText: true,
                validator: _validatePassword,
              ),
              const SizedBox(height: 20),
              Center(
                child: ElevatedButton(
                  onPressed: _submit,
                  child: const Text('Submit'),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

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

This Flutter screen uses a Form widget with a GlobalKey to manage validation state. It has two TextFormField widgets:

  • The email field uses a regular expression to check if the input looks like a valid email address.
  • The password field checks if the input is at least 6 characters long.

If either field is invalid, an error message appears below it. When the user taps the Submit button, the form validates all fields. If all are valid, a SnackBar shows a success message.

This approach helps users fix mistakes before submitting, making the app friendlier and more reliable.

Final Result
Completed Screen
-------------------------
| Simple Form Validation |
-------------------------
| Email:                |
| [user@example.com   ] |
|                       |
| Password:             |
| [••••••••••••••••••] |
|                       |
|                       |
|       [ Submit ]       |
-------------------------
User types email and password
If input is invalid, error messages appear below fields
Tapping Submit validates inputs
If valid, a SnackBar appears with 'Form submitted successfully!'
Stretch Goal
Add a toggle icon to show or hide the password text
💡 Hint
Use a boolean state variable to switch obscureText on the password TextFormField and an IconButton inside the field's suffixIcon

Practice

(1/5)
1. What does the validator property in a TextFormField do in Flutter?
easy
A. It clears the input field when pressed.
B. It styles the text inside the field.
C. It saves the input value to a database.
D. It checks the user input and returns an error message if invalid.

Solution

  1. Step 1: Understand the role of validator

    The validator property is used to check if the input meets certain rules.
  2. Step 2: What validator returns

    If the input is invalid, it returns a string error message; if valid, it returns null.
  3. Final Answer:

    It checks the user input and returns an error message if invalid. -> Option D
  4. Quick Check:

    Checks user input and returns error if invalid = D [OK]
Hint: Validator returns error string if input invalid, else null [OK]
Common Mistakes:
  • Thinking validator styles the field
  • Assuming validator saves data
  • Confusing validator with input clearing
2. Which of the following is the correct syntax to add a validator that checks if input is empty in a TextFormField?
easy
A. validator: (value) => value.length == 0 ? 'Enter text' : null,
B. validator: (value) => value.isEmpty ? 'Enter text' : null,
C. validator: (value) { if (value == null || value.isEmpty) return 'Enter text'; else return null; },
D. validator: (value) => if(value.isEmpty) 'Enter text';

Solution

  1. Step 1: Check syntax for validator function

    The validator must be a function returning a string or null. validator: (value) { if (value == null || value.isEmpty) return 'Enter text'; else return null; }, uses a proper function with if-else, null check, and returns correctly.
  2. Step 2: Identify syntax errors in other options

    B uses shorthand but lacks null check before value.isEmpty which throws if null. C uses length but lacks null check before accessing value.length which throws if null. D has invalid syntax with if without ternary or braces.
  3. Final Answer:

    validator: (value) { if (value == null || value.isEmpty) return 'Enter text'; else return null; }, -> Option C
  4. Quick Check:

    Full function with null check and proper returns = A [OK]
Hint: Use full function with return for validator to avoid syntax errors [OK]
Common Mistakes:
  • Missing return statements
  • Incorrect if syntax inside lambda
  • Not handling null safety properly
3. Given this validator code in a TextFormField:
validator: (value) {
  if (value == null || value.isEmpty) {
    return 'Please enter text';
  } else if (value.length < 5) {
    return 'Minimum 5 characters';
  }
  return null;
}
What error message will show if the user enters "abc"?
medium
A. Minimum 5 characters
B. Please enter text
C. null (no error)
D. Syntax error

Solution

  1. Step 1: Check if input is null or empty

    The input "abc" is not null and not empty, so the first if condition is false.
  2. Step 2: Check length condition

    "abc" length is 3, which is less than 5, so the second condition is true and returns 'Minimum 5 characters'.
  3. Final Answer:

    Minimum 5 characters -> Option A
  4. Quick Check:

    Length less than 5 triggers 'Minimum 5 characters' = B [OK]
Hint: Check conditions in order; first true returns error [OK]
Common Mistakes:
  • Ignoring length check
  • Assuming empty error for non-empty input
  • Confusing return null with error string
4. Identify the error in this validator code snippet:
validator: (value) {
  if (value.isEmpty) {
    return 'Required';
  }
  return null;
}
medium
A. Missing null check for value before calling isEmpty
B. Should return true instead of null when valid
C. Validator must be async function
D. No error, code is correct

Solution

  1. Step 1: Check null safety for value

    The validator function receives a nullable String? value, so calling value.isEmpty without checking for null causes a runtime error.
  2. Step 2: Correct way to check null or empty

    Must check if value == null or value.isEmpty before using isEmpty alone.
  3. Final Answer:

    Missing null check for value before calling isEmpty -> Option A
  4. Quick Check:

    Null safety requires checking value before isEmpty = C [OK]
Hint: Always check for null before using isEmpty on input [OK]
Common Mistakes:
  • Ignoring null safety
  • Returning true instead of null
  • Thinking validator must be async
5. You want to validate a password field with these rules: - Must not be empty - Must be at least 8 characters - Must contain at least one digit Which validator function correctly implements these rules?
hard
A. validator: (value) { if (value.isEmpty) return 'Password required'; if (value.length < 8) return 'At least 8 chars'; if (!value.contains(RegExp(r'\d'))) return 'Must contain digit'; return null; },
B. validator: (value) { if (value == null || value.isEmpty) return 'Password required'; if (value.length < 8) return 'At least 8 chars'; if (!RegExp(r'\d').hasMatch(value)) return 'Must contain digit'; return null; },
C. validator: (value) { if (value == null) return 'Password required'; if (value.length <= 8) return 'At least 8 chars'; if (!RegExp(r'\d').hasMatch(value)) return 'Must contain digit'; return null; },
D. validator: (value) { if (value == null || value.isEmpty) return 'Password required'; if (value.length <= 8) return 'At least 8 chars'; if (!RegExp(r'\d').hasMatch(value)) return 'Must contain digit'; return null; },

Solution

  1. Step 1: Check null or empty condition

    validator: (value) { if (value == null || value.isEmpty) return 'Password required'; if (value.length < 8) return 'At least 8 chars'; if (!RegExp(r'\d').hasMatch(value)) return 'Must contain digit'; return null; }, correctly checks if value is null or empty and returns 'Password required'. Options B and C miss null safety or empty check properly.
  2. Step 2: Check length and digit rules

    validator: (value) { if (value == null || value.isEmpty) return 'Password required'; if (value.length < 8) return 'At least 8 chars'; if (!RegExp(r'\d').hasMatch(value)) return 'Must contain digit'; return null; }, uses < 8 for length which means minimum 8 chars required. It uses RegExp to check digit presence correctly. Options C and D use <= 8 which wrongly rejects 8-char passwords.
  3. Final Answer:

    validator: (value) { if (value == null || value.isEmpty) return 'Password required'; if (value.length < 8) return 'At least 8 chars'; if (!RegExp(r'\d').hasMatch(value)) return 'Must contain digit'; return null; }, -> Option B
  4. Quick Check:

    Null safety + <8 length + digit regex = A [OK]
Hint: Check null, length & regex carefully; use < not <= for min length [OK]
Common Mistakes:
  • Ignoring null safety
  • Using <= instead of < for length
  • Incorrect regex usage
  • Missing empty string check
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard