This article contains full information about Flutter form and form validation in flutter Application, all of that with example code.
What is form?
A form is a window or a screen that contains fields or some space to enter data. A form is an easy way to collect some specific data from users. For example, the user’s name, email, address, phone number, date of birth, etc. The data may be used for searching, saving user info, filtering, logging in, or something else.
What is validation?
Validations are actually the constraints or restrictions on the data to be collected from the user. For example, if we want to collect some data about a person, let’s say his name, email, and phone number. We will force the user to enter only a valid name, a valid email, and a valid phone number. We need form validation for this.
In flutter, you can do validation in two ways. One way to do it is by using the validator package and the other way is by using Regular Expressions (Regex). In our example app, we use the validator package along with regex. The validator package makes things very simple. You need to type only a few lines of code. It also provides a simple way to use regex for validation very easily.
Form in flutter
There is a form widget in flutter which provides all the facilities a form needs. Here we group and validate multiple form fields. flutter form can contain text fields, buttons, radio buttons, check boxes, etc
It is important to note that when you create a form you should provide a Global key. The Global key is used to identify the form and validate the form fields. Here we create a simple app that takes a name, an email, a phone number, and a password. We use a submit button that calls the validate() method through _formkey. This method actually does the validations. Then you can do further things with your form data. Following are some screenshots of our app.
Our form with valid data entered
Our form with invalid data entered
Our form with no data entered
Coding the app
Before starting to code, you need to add the following dependency for the validator package in your pubspec.yaml file.
form_field_validator: ^1.1.0
After that in the main.dart file in your lib folder, write the following code.
import 'package:flutter/material.dart';
import 'package:form_field_validator/form_field_validator.dart';
import 'testing_form.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: "Basic App",
theme: ThemeData(primarySwatch: Colors.green),
home: const TestingForm(),
);
}
}
class TestingForm extends StatelessWidget {
const TestingForm({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Custom Form')),
body: const MyCustomForm(),
);
}
}
class MyCustomForm extends StatefulWidget {
const MyCustomForm({Key? key}) : super(key: key);
@override
State<MyCustomForm> createState() => _MyCustomFormSate();
}
class _MyCustomFormSate extends State<MyCustomForm> {
final _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(30),
child: SingleChildScrollView(
child: Form(
key: _formKey,
autovalidateMode: AutovalidateMode.always,
child: Column(
children: [
TextFormField(
decoration: const InputDecoration(
hintText: 'Enter your name',
label: Text('Name'),
border: OutlineInputBorder(),
),
validator: MultiValidator([
RequiredValidator(errorText: "Name required"),
MinLengthValidator(6,
errorText: "Name must be at least of 6 chars"),
]),
),
const SizedBox(height: 20),
TextFormField(
decoration: const InputDecoration(
hintText: 'Enter your Email',
label: Text('Email'), border: OutlineInputBorder(),
),
validator: MultiValidator([
RequiredValidator(errorText: "Email required"),
EmailValidator(errorText: "Please insert a valid email")
]),
),
const SizedBox(height: 20),
TextFormField(
keyboardType: TextInputType.number,
decoration: const InputDecoration(
hintText: 'Phone number',
label: Text('Phone'),
border: OutlineInputBorder(),
),
validator: MultiValidator([
RequiredValidator(errorText: "Phone number required"),
PatternValidator(r'^(?:[+0][1-9])?[0-9]{10,12}$',
errorText: ''),
]),
),
const SizedBox(height: 20),
TextFormField(
obscureText: true,
decoration: const InputDecoration(
hintText: 'Enter password',
label: Text('password'),
border: OutlineInputBorder(),
),
validator: MultiValidator([
RequiredValidator(errorText: 'password is required'),
MinLengthValidator(8, errorText: 'password must be at
least 8 digits long'),
PatternValidator(r'(?=.*?[#?!@$%^&*-])', errorText:
'passwords must have at least one special character')
]),
),
const SizedBox(height: 30),
SizedBox(
height: 30,
width: 200,
child: ElevatedButton(
child: const Text("Submit"),
onPressed: () {
if (_formKey.currentState!.validate()) {}
},
),
),
],
),
),
),
);
}
}
How does the code work?
The class MyCustomForm that extends StatefulWidget is a base for _MyCustomFormSate class which extends state. In _MyCustomFormSate class we create a GlobalKey that will identify the form and validate the form fields. In the build method, we take the form of a child of the SingleChildScrollView widget. Note one thing here if you take form directly as a child of padding you will get a bottom overflow error when the keyboard appears on screen for input.
The following figure shows our app when no SingleChildScrollView widget is used. You can see here black and yellow lines above the keyboard showing a message BOTTOM OVERFLOWED BY 159 PIXELS”. So it is good practice to take the form in SingleChildScrollView to avoid these problems.
The form widget
The form widget takes a key _form_key. There are four TextFormFeilds for name, email, phone number, and password. The TextFormFeild takes the decoration property through which we can decorate the TextFormField. Here we have provided hint text, Label, and border to our TextFormField. The TextFormFeild takes another property validator through which we validate the user’s input.
Validating the TextFormFeild
For all TextFormFeilds, we have used a MultiValidator widget from the Validator package. The MultiValidator widget provides a way to apply multiple validations on the TextFormFeild. Here we have used RequiredValidator which ensures that the TextFormFeild should not be empty. It also takes an error Text that displays a message to the user.
In our case we have written the messages “Name required”, “Email required”, “Phone Number Required” and “Password required”. Along with this, we have used MinLengthValidator which ensures the minimum characters required for the TextFormFeild. It takes an argument that specifies the minimum length. In our case, for the name, it is 6. For the password, it is 8.
For email, we have used EmailValidator which automatically validates email. It takes an error message too…
For a phone number, we have used a PatternValidator. A PatternValidator takes a regular expression instead of built-in validations along with an error message. If you don’t know about Regular expressions or Regex. Please check it from somewhere.
The last thing to validate here is our password. For passwords, we used a regular expression that takes a password with at least one special character. The TextFormFeild takes a property of obscure text that hides the input characters. This is used for passwords.
Thanks
Dependency: (https://pub.dev/packages/form_field_validator).