Bird
Raised Fist0
Fluttermobile~5 mins

Form validation rules in Flutter

Choose your learning style10 modes available
Introduction

Form validation rules help check if the information entered by a user is correct before saving or sending it. This avoids mistakes and keeps data clean.

When asking users to enter their email or phone number to make sure it looks right.
When creating a signup form to ensure passwords are strong and match.
When collecting feedback to make sure required fields are not empty.
When submitting orders to confirm all necessary details are filled in.
When building any form where user input needs to be checked for errors.
Syntax
Flutter
TextFormField(
  validator: (value) {
    if (value == null || value.isEmpty) {
      return 'Please enter some text';
    }
    return null;
  },
)

The validator function returns a string error message if the input is invalid.

If the input is valid, the validator must return null.

Examples
Checks if the field is empty and shows an error if it is.
Flutter
TextFormField(
  validator: (value) {
    if (value == null || value.isEmpty) {
      return 'Field cannot be empty';
    }
    return null;
  },
)
Checks if the input contains '@' to validate a simple email format.
Flutter
TextFormField(
  validator: (value) {
    if (value == null || !value.contains('@')) {
      return 'Enter a valid email';
    }
    return null;
  },
)
Ensures the password is at least 6 characters long.
Flutter
TextFormField(
  validator: (value) {
    if (value == null || value.length < 6) {
      return 'Password must be at least 6 characters';
    }
    return null;
  },
)
Sample App

This app shows a form with email and password fields. When you tap Submit, it checks if the email contains '@' and if the password is at least 6 characters. If there are errors, it shows messages below the fields. If all is good, it shows a small message at the bottom saying 'Processing Data'.

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

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('Form Validation Example')),
        body: const Padding(
          padding: EdgeInsets.all(16),
          child: MyCustomForm(),
        ),
      ),
    );
  }
}

class MyCustomForm extends StatefulWidget {
  const MyCustomForm({super.key});

  @override
  State<MyCustomForm> createState() => _MyCustomFormState();
}

class _MyCustomFormState extends State<MyCustomForm> {
  final _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    return Form(
      key: _formKey,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          TextFormField(
            decoration: const InputDecoration(labelText: 'Email'),
            validator: (value) {
              if (value == null || value.isEmpty) {
                return 'Please enter your email';
              }
              if (!value.contains('@')) {
                return 'Please enter a valid email';
              }
              return null;
            },
          ),
          const SizedBox(height: 16),
          TextFormField(
            decoration: const 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;
            },
          ),
          const SizedBox(height: 24),
          ElevatedButton(
            onPressed: () {
              if (_formKey.currentState!.validate()) {
                ScaffoldMessenger.of(context).showSnackBar(
                  const SnackBar(content: Text('Processing Data')),
                );
              }
            },
            child: const Text('Submit'),
          ),
        ],
      ),
    );
  }
}
OutputSuccess
Important Notes

Always return null from the validator if the input is valid.

You can combine multiple checks inside one validator function.

Use GlobalKey<FormState> to manage the form state and trigger validation.

Summary

Form validation rules check user input and show helpful error messages.

Use the validator property on TextFormField to add rules.

Return a string error message if invalid, or null if valid.

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