How to perform text field validation in Flutter using Form

Text field validation is essential to building user-friendly Flutter applications. It ensures that the data entered by users in text fields meets the required criteria, such as being non-empty, of a specific length, or matching a particular pattern. Validating text fields using forms helps improve data integrity and enhances the user experience by providing immediate feedback on any input errors. In Flutter, you can perform text field validation efficiently by utilizing the built-in form widgets and validation mechanisms.

Implementation

We can follow the instructions given below to implement validation in the text field using Form.

Create basic UI

Firstly, we can create a StatelessWidget subclass that will contain a Form widget with two TextFormFields. One is for email and another one is for password validation, and an ElevatedButton to submit the form.

class TextFieldValidationExample extends StatelessWidget{
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Text Field Validation Example'),
),
body: Form(
child: Column(
children: [
const SizedBox(height: 50),
TextFormField(
decoration: InputDecoration(
labelText: "Email"
),
),
const SizedBox(height: 24),
TextFormField(
decoration: InputDecoration(
labelText: "Password",
),
maxLength: 6,
obscureText: true,
),
const SizedBox(height: 50),
ElevatedButton(
onPressed: () { },
child: Text("Submit")
),
],
),
),
);
}
}

If we run the above code in a Flutter project, we will get the following output  without any validation.

Simple UI without validation
Simple UI without validation

Create an input validation mixin

We can create a mixin to handle the validation logic as shown below.

mixin ValidationMixin {
bool isPasswordValid(String inputpassword) => inputpassword.length == 6;
bool isEmailValid(String inputemail) {
Pattern pattern =
r'^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))';
RegExp regexp = new RegExp(pattern);
return regexp.hasMatch(inputemail);
}
}
  • Line 1: We declare a mixin name ValidationMixin to reuse this code at multiple places.

  • Line 2: We define a method name isPasswordValid that takes a String parameter inputpassword and returns a boolean value after comparing the length of inputpassword.

  • Line 4: We define a method name isEmailValid that takes a String parameter inputemail and returns a boolean value.

  • Lines 5–6: We create an Pattern object named pattern that defines a regular expression representing a common structure for a valid email address. The r prefix before the pattern indicates that it is a raw string.

  • Line 7: Then we create a RegExp object named regexp using the pattern defined earlier. It allows us to perform different operations on regular expressions.

  • Line 8: This line uses the hasMatch method of the RegExp object to check whether the inputEmail matches the pattern. The hasMatch method returns true if there is a match and false otherwise.

Now add the ValidationMixin to TextFieldValidationExample like this.

class TextFieldValidationExample extends StatelessWidget with ValidationMixin {
// remaining code
}

Define a global key

The Form widget, acting as a container, allows us to validate multiple TextFormField. To uniquely identify the form, we utilize a GlobalKey. Additionally, the GlobalKey is used to access the current state of the form. It can be defined as follows:

final formGlobalKey = GlobalKey<FormState>();

Now add this key to the Form widget as,

Form(
key: formGlobalKey,
// rest of the code defined here
),

Add validator method to TextFormField

To validate the Form fields, use the validator property available in TextFormField. This property takes a validation function that receives the input value and returns a string error message if the input is invalid. We will pass the validation functions from the mixin to the validator functions of the TextFormFields as shown below.

TextFormField(
validator: (email) {
if (isEmailValid(email)) return null;
else
return 'Enter a valid email address';
},
),
TextFormField(
obscureText: true,
validator: (password) {
if (isPasswordValid(password)) return null;
else
return 'Enter a valid password';
},
),

Add validation logic to submit button

When the user presses the submit button, we access the form's currentState property using GlobalKey. We determine whether to utilize the user information by checking if the form is valid. If the form is not valid, we display an appropriate error message.

ElevatedButton(onPressed: () {
if (formGlobalKey.currentState.validate()) {
// use the information provided
}
}, child: Text("Submit"))

Output

We get the following output by putting together the code explained above.

import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp(
    debugShowCheckedModeBanner: false,
    home: TextFieldValidationExample(),
  ));
}

class TextFieldValidationExample  extends StatelessWidget with ValidationMixin {
  final formGlobalKey = GlobalKey < FormState > ();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Text Field validation example'),
      ),
      body:
      Padding(
        padding: const EdgeInsets.symmetric(horizontal: 24),
          child: Form(
            key: formGlobalKey,
            child: Column(
              children: [
            const SizedBox(height: 50),
                  TextFormField(
                    decoration: InputDecoration(
                      labelText: "Email"
                    ),
                    validator: (email) {
                      if (isEmailValid(email)) return null;
                      else
                        return 'Email address is not valid';
                    },
                  ),
                  const SizedBox(height: 24),
                    TextFormField(
                      decoration: InputDecoration(
                        labelText: "Password",
                      ),
                      maxLength: 6,
                      obscureText: true,
                      validator: (password) {
                        if (isPasswordValid(password)) return null;
                        else
                          return 'Password length is short.';
                      },
                    ),
                    const SizedBox(height: 50),
                      ElevatedButton(
                        onPressed: () {
                          if (formGlobalKey.currentState.validate()) {
                            formGlobalKey.currentState.save();
                            // use the email provided here
                          }
                        },
                        child: Text("Submit"))
          ],
            ),
          ),
      ));
  }
}

mixin ValidationMixin {
  bool isPasswordValid(String inputpassword) => inputpassword.length == 6;

  bool isEmailValid(String inputemail) {
    Pattern pattern =
      r'^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))';
    RegExp regexp = new RegExp(pattern);
    return regexp.hasMatch(inputemail);
  }
}

Free Resources

Copyright ©2025 Educative, Inc. All rights reserved