Flutter has many different types of built-in input widgets like DatePicker, Checkbox, Slider, Radio Button, and Dropdown Button amongst others for the time being we’re going to focus on the text.
Everybody has used TextField to get information from the user. TextField is a simple widget, which simply means a way of capturing a collection of data from the end-user.

As you can see we have a simple text field widget. By default when you add a TextField you will get the material styling.
Input Decoration
This allows to added behavior object without affecting the object itself. It will add visual enhancements to your TextFormField without actually changing the text because the TextFormField itself is pretty basic.
TextFormField(decoration: const InputDecoration(
icon: const Icon(Icons.person),
hintText: 'Enter your name',
labelText: 'Name'),
....)
Input widgets can accept a number of properties. You can change the fill color, content patent, content padding, border ever border focus. You could change how that site with a disabled counter text.
The InputDeclaration does have some limitations. Label and Error messages are limited to text only. If you want a label then that’s possible but if you want to add a star for required or if you want to add an exclamation mark if your message is invalid then it’s not possible.
As many of you know that to make apps secure you want to make sure that the information that users enter is valid and you want to display a nice friendly message as you can see.

Flutter Form Framework
You can probably come up with your own validation framework but Flutter has a set of form widgets that manages validation along with other features as well.

There are two types of widgets Form and FormField<T>
. This represents Form in the widget tree and a Form will have FormField descendants that could be the string, int, or a custom class.
The Form widgets maintain the states of the FormField and it stores data such as the current value and the validity.
Each FormField can handle its own validation but Form itself can coordinate and once validates every FormField widget. It can traverse down the tree, find every descendent of FormField and validate each one in turn.

FormField is a wrapper that adds validation to an existing input widget. It can also add saving and reset functionality. It’s uniform and consistent across all form widgets.
Validating TextFormField
Now I’m just going to explain a little bit more about validating TextFormFields.
1.Create a Form with a global key.
final _formKey = GlobalKey<FormState>();
...
body: Center(
child: Form(
key: _formKey,
autovalidate: false,
....
In the case of a TextFormField the first thing you would do is create a Form and create a GlobalKey of the type FormField state. Then you will add that key to your Form
2. Add a FormField with validation logic
TextFormField( .....
validator: (value) {
if (value.isEmpty) {
return 'Please enter name';
}
return null;
},
It’s simple as you see there we want to make sure that username is required. Make sure that there is a value if not then the field is invalid and we will turn the message otherwise we return null indicating that is valid.
3. Create a button to validate and submit of the Form
Finally, we can call the validate function and then we submit the data.
onPressed: () {
if (_formKey.currentState.validate()) {
print("Process data");
...
} else {
print('Error');
}
},
child: Text('Create'),
),
How validation work
It records the valid function of every single FormField. Every FormField has its own validate function and within that validate function it will invoke the validator. The error message is displayed in the TextField. If FormFields is invalid this function will return false if all FormField is valid then it will return true and you can go ahead and process and submit the data.
String Length Validation
Simply add this code to any TextFormField to limit the length of characters to the passed-in value. In our case, we will limit the name to 20 characters.
TextFormField(
......
[new LengthLimitingTextInputFormatter(20)],)
Phone Number Validation
A keyboard type of phone makes it easier for a user to enter a phone number. For our validation, we’ll use a standard 10-digit Indian phone format.
TextFormField(
...
keyboardType: TextInputType.phone,
inputFormatters: [
new WhitelistingTextInputFormatter(
new RegExp(r'^[0-9]*$')),
new LengthLimitingTextInputFormatter(10)
],
...
),
What the above pattern does is essentially create a whitelist of characters we want to allow the user to enter. If a character doesn’t match this whitelist, it is discarded and not allowed to be entered. This keeps the user from entering anything other than digits.
final RegExp phoneRegex = new RegExp(r'^[6-9]\d{9}$');
TextFormField(
....
validator: (value) {
if (!phoneRegex.hasMatch(value)) {
return 'Please enter valid phone number';
}
return null;
},
...
),
In addition to whitelisting characters, we need to tell the user when they have an issue with their entry.
Email Address Validation
The email address entered by the user will be validated against this regular expression and if it doesn’t pass, then the user will see a message informing them to correct their entry.
final RegExp emailRegex = new RegExp(
r"^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,253}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,253}[a-zA-Z0-9])?)*$");
TextFormField(
...
keyboardType: TextInputType.emailAddress,
validator: (value) {
if (!emailRegex.hasMatch(value)) {
return 'Please enter valid email';
}
return null;
},
...
),
Password Cross Input Validation
The confirm password field needs to know the value of the password field in order to check that the passwords don’t match.
final _passwordFieldKey = GlobalKey<FormFieldState<String>>();
TextFormField(
key: _passwordFieldKey,
obscureText: true,
....
),
TextFormField(
obscureText: true,
decoration: const InputDecoration(
labelText: 'Conform Password'),
validator: (value) {
if (value != _passwordFieldKey.currentState.value) {
return 'Password do not match';
}
return null;
},
),
We can create a password field kay. When we pass that key into our TextFormField we can get access to the state of the password field and then get the value and then here we can do our check and then return the desired error message.
The Save Function
Another feature of the FormField is save()
function. The save function will allow you just to save all the values at once if you want to save the values on submission. It’s pretty simple you have a save() function, in this case, we’re just assigning the value to the state variable.
TextFormField(
...
onSaved: (value) {
user.phoneNo = value;
},
),
Like validate()
what save will do is it will go through every FormField and invoke save functional every form filter to invoke the save function of every FormField.
Auto Validation
Use the auto-validate property if you want to validate on change. A lot of the time when you have a form you want the validation. What you can do is that once you press submit for the first time you can set auto validate to true so that as soon as you correct your mistake the other message goes away.
Related Post
- How to design Flutter app according to different screen sizes(Adaptive).
- Display Auto Size AlertDialog with ListView in Flutter