Ultimate Guide to Flutter Form Validation using Form Builder (2026)

Learn how to implement Form Validation in Flutter easily using the flutter_form_builder package. A step-by-step tutorial for beginner developers with source code

Last updated Jan 18, 2026

Are you struggling to manage complex forms in your Flutter app? Handling multiple text fields, radio buttons, and validation logic with the standard Flutter Form widget can quickly become messy and verbose.

 

Enter Flutter Form Builder

In this tutorial, we will master Flutter form validation using the flutter_form_builder package. This tool simplifies data collection, reduces boilerplate code, and makes validating user input (like emails and passwords) incredibly easy. By the end of this guide, you will be able to build robust, professional forms for your Android and iOS apps.

 

Why Use flutter_form_builder?

  • Less Code: Reduces the boilerplate required for standard TextFormFields.

  • Built-in Validation: easy integration with form_builder_validators.

  • Unified State: Access all form data in a single Map.

  • Wide Widget Support: Comes with ready-made widgets for DatePickers, Chips, Sliders, and more

 


 

1. Getting Started: Installation

 

First, we need to add the necessary packages to your project. Open your pubspec.yaml file and add the following dependencies under dependencies:

 

dependencies:
  flutter:
    sdk: flutter
  flutter_form_builder: ^9.0.0  # Check pub.dev for the latest version
  form_builder_validators: ^10.0.0

 

Run the following command in your terminal to install them:

 

flutter pub get

 

 


 

2. Setting Up the Form Structure

To create a form, we need to wrap our fields in a FormBuilder widget. This widget acts as a container that manages the state of all its children.

 

Key Concepts for Beginners:

  • GlobalKey: Think of this as a "remote control" for your form. It allows you to trigger validation or reset the form from anywhere (like when a button is pressed).

 

  • name property: Every field in flutter_form_builder MUST have a unique name. This acts as the ID for that piece of data (e.g., 'email', 'password').

 

The Basic Code Setup

Here is the skeleton of a login screen using Form Builder

 

import 'package:flutter/material.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:form_builder_validators/form_builder_validators.dart';

class LoginForm extends StatefulWidget {
  const LoginForm({Key? key}) : super(key: key);

  @override
  State createState() => _LoginFormState();
}

class _LoginFormState extends State {
  // 1. Create the GlobalKey to access the form state
  final _formKey = GlobalKey();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("Flutter Form Builder Demo")),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: FormBuilder(
          key: _formKey,
          child: Column(
            children: [
              // We will add form fields here
            ],
          ),
        ),
      ),
    );
  }
}

 


 

3. Adding Fields with Validation

Now, let's add an Email field and a Password field. We will use FormBuilderValidators to ensure the user enters valid data.

 

Adding an Email Field

FormBuilderTextField(
  name: 'email', // Unique key for this field
  decoration: const InputDecoration(
    labelText: 'Email Address',
    border: OutlineInputBorder(),
    prefixIcon: Icon(Icons.email),
  ),
  // Validators ensure data integrity
  validator: FormBuilderValidators.compose([
    FormBuilderValidators.required(),
    FormBuilderValidators.email(errorText: "Please enter a valid email"),
  ]),
),
const SizedBox(height: 15),

 

Adding a Password Field

FormBuilderTextField(
  name: 'password',
  obscureText: true, // Hides the text for passwords
  decoration: const InputDecoration(
    labelText: 'Password',
    border: OutlineInputBorder(),
    prefixIcon: Icon(Icons.lock),
  ),
  validator: FormBuilderValidators.compose([
    FormBuilderValidators.required(),
    FormBuilderValidators.minLength(6, errorText: "Password must be at least 6 characters"),
  ]),
),
const SizedBox(height: 20),

 


 

4. Handling Submission and Data Retrieval

 

The final step is to create a submit button. When clicked, we want to:

  1. Check if the form is valid (no red error messages).

  2. Save the data.

  3. Print or send the data

ElevatedButton(
  onPressed: () {
    // Validate and save the form
    if (_formKey.currentState?.saveAndValidate() ?? false) {
      // If true, the form is valid.
      // Get the values from the form state
      final formData = _formKey.currentState?.value;
      
      print("Form Data: $formData");
      print("Email: ${formData?['email']}");
      
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('Validation Successful! Processing Data...')),
      );
    } else {
      print("Validation failed");
    }
  },
  child: const Text('Login'),
)

 


Full Source Code Example

Flutter Form Builder

Copy and paste this code into your main.dart file to see the complete Flutter Form Builder example in action

 

import 'package:flutter/material.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:form_builder_validators/form_builder_validators.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Form Validation Tutorial',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const LoginForm(),
    );
  }
}

class LoginForm extends StatefulWidget {
  const LoginForm({Key? key}) : super(key: key);

  @override
  State createState() => _LoginFormState();
}

class _LoginFormState extends State {
  final _formKey = GlobalKey();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("Form Builder Beginner Guide")),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(20.0),
        child: FormBuilder(
          key: _formKey,
          // autovalidateMode: AutovalidateMode.onUserInteraction, // Optional: Validates as you type
          child: Column(
            children: [
              const Text(
                "Welcome Back!",
                style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
              ),
              const SizedBox(height: 20),
              
              // Email Field
              FormBuilderTextField(
                name: 'email',
                decoration: const InputDecoration(
                  labelText: 'Email',
                  border: OutlineInputBorder(),
                  prefixIcon: Icon(Icons.email_outlined),
                ),
                validator: FormBuilderValidators.compose([
                  FormBuilderValidators.required(),
                  FormBuilderValidators.email(),
                ]),
              ),
              const SizedBox(height: 15),

              // Password Field
              FormBuilderTextField(
                name: 'password',
                obscureText: true,
                decoration: const InputDecoration(
                  labelText: 'Password',
                  border: OutlineInputBorder(),
                  prefixIcon: Icon(Icons.lock_outline),
                ),
                validator: FormBuilderValidators.compose([
                  FormBuilderValidators.required(),
                  FormBuilderValidators.minLength(6),
                ]),
              ),
              const SizedBox(height: 15),

              // Terms and Conditions
              FormBuilderCheckbox(
                name: 'accept_terms',
                title: const Text("I accept the terms and conditions"),
                validator: FormBuilderValidators.equal(
                  true, 
                  errorText: "You must accept terms to continue"
                ),
              ),
              const SizedBox(height: 20),

              // Submit Button
              SizedBox(
                width: double.infinity,
                child: ElevatedButton(
                  style: ElevatedButton.styleFrom(
                    padding: const EdgeInsets.symmetric(vertical: 15),
                  ),
                  onPressed: () {
                    if (_formKey.currentState?.saveAndValidate() ?? false) {
                      final formData = _formKey.currentState?.value;
                      debugPrint(formData.toString());
                      // Navigate to next page or call API here
                    } else {
                      debugPrint("Validation Failed");
                    }
                  },
                  child: const Text("Submit", style: TextStyle(fontSize: 18)),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

 


 

 

Common Questions (FAQ)

Q: How do I get the value of a specific field? A: You can access the entire form map using _formKey.currentState?.value or a specific field using _formKey.currentState?.fields['email']?.value.

 

Q: Can I create custom validators? A: Yes! You can pass a custom function to the validator property. If the data is invalid, return a String (the error message); otherwise, return null.

 

Q: Is this package safe for production apps? A: Absolutely. flutter_form_builder is one of the most widely used and maintained packages in the Flutter ecosystem.

 

Conclusion

Mastering Flutter form validation is a critical skill for any app developer. By using flutter_form_builder, you save time, write cleaner code, and provide a better user experience with robust error handling.

 

Start experimenting with other fields like FormBuilderSlider or FormBuilderDateTimePicker to see how powerful this package really is!

 

Related Tutorials & Resources