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.
We can follow the instructions given below to implement validation in the text field using Form
.
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{@overrideWidget 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.
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}
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),
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;elsereturn 'Enter a valid email address';},),TextFormField(obscureText: true,validator: (password) {if (isPasswordValid(password)) return null;elsereturn 'Enter a valid password';},),
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"))
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