Reactive Forms in Flutter have never been so easy
There is almost no application that doesn’t have forms. Data acquisition, authentication, and profiling are some of the primary use cases for an application to include any Form. Also, forms are the preferred point of pressure for QA testers as data validation is one of the most attacked points for those who try to find holes in our applications. That is why making a form can be painful for developers regardless of the framework or language. Making a good form is always hard to do if you need to look for all the edge cases.
In this article, I will contrast classical forms in flutter and a package that I think made my life easier since I started to use it in its early versions. I’m talking about reactive_forms.
What we will do is:
- Scaffold the project.
- Create two identical forms, one using Flutter Forms and the other using Reactive Forms.
- Validate form fields.
- Get form data.
- Disable the button on an invalid form.
First, I would like to thank the package creator for his work and the community for the support. I encourage you to give the package a Like 👍 in pub.dev and a Star ⭐️ on Github if you use it and find it helpful.
1. Scaffold the project
Start by creating a new project and modifying the lib/main.dart to remove any unnecessary comments and code. In MyHomePage create two buttons, one for showing the Flutter Form version and the other for the Reactive Form Version. The result should be like this view:
After this create two separate files under /lib folder: flutter_form_example.dart and reactive_form_example.dart. Now add navigation to these views from MyHomePage by doing:
Now everything is ready to move to the next chapter 👌.
2. Create two identical forms, one using Flutter Forms and the other using Reactive Forms.
2.1 Create the Flutter Form
To create the flutter form just copy/paste the below code.
2.2 Create Reactive Form
For the reactive form version, there are several ways of creating a Form. This article will use a simple one, but you can read the package documentation to find and try the others.
In reactive forms “A form is composed of multiple fields or controls.”. A FormGroup is the main component for creating forms. It can contain FormControls but also can include more complex structures such as FormArrays or other nested FormControls. (Read more).
On the 12th line, the FormGroup is created. The form group is a Map that contains the FormControlName and the FormControl object. The main widget to host our form is the ReactiveForm widget. It will hold all the reactive widgets such as ReactiveTextField (cousin of the TextFormField), ReactiveCheckboxListTile, and so on.
Also, wrap the Button in a ReactiveFormConsumer. This widget will have the updated state of the form in its builder. Then flutter doesn’t repaint all the view when the form states changes.
At this point, we have two similar views. The code is not much different for the two versions because the fun part begins here.
3. Validate form fields
Now we are going to validate the fields following the next rules:
- Nickname: Required. Only alphanumeric characters, can’t have jumps or spaces. Characters “-”, “_”, and “.” are allowed.
- Email: Required. Must be a valid email string.
- Comment: Max length 120 characters.
- Terms and conditions are mandatory to be selected.
For validating the Nickname and Email fields add the validator property in TextFormField, then use RegExp validate using these regular expressions:
Also set autovalidateMode: AutovalidateMode.onUserInteraction for having the fields be validated as the user types. For Nickname and Comment fields use the property maxLength to validate and show the max length visible on the form. This is the native way of validating Form fields.
Then in the Submit Button, when pressed check the validity of the fields, and also if Terms and Conditions were checked to act. The result is next:
The Reactive Form side needs way less code to do this.
First, modify FormGroup to include validators. Use Validators.required for required fields, Validators.email for Email field, and Validators.pattern for the RexExp of the Nickname field.
Then add the ValidationMessages to the fields and that’s it.
At this point, you see the difference. While in flutter we needed to code a lot of boilerplate for doing the validations, in reactive forms was very easy and without so much code.
4. Get form data
Getting the form data is not simple in flutter form. For this, there are several approaches but the one used in the flutter cookbook is using TextEditingControllers, one for each TextFormField. So we are going to follow this approach. Then show the data on the SnackBar:
First, create the text editing controllers and add them to the TextFormFields on the property: controller.
Then show the data in the SnackBar
On the reactive form side, we don’t need too much for this. The form object in the ReactiveFormConsumer builder has the property value which returns a Map with the values for each control. So just ad this code to the Submit Button
5. Disable the button on an invalid form
One of the best ways of telling the user that he has validation errors is by disabling the button if the form is invalid.
On the flutter side we need to create the next workaround:
- Add a boolean variable to hold the validation state.
- Add a listener on the onChanged property of the form to set the state and change the value of that variable
- Make the onPressed property of the Submit Button conditional to return null if the variable is false
In reactive form just check the property valid of the form in the onPressed property of the Submit Button.
Conclusion
This way this ends. I’ve tried to demonstrate here that it is very easy and useful to use reactive_forms to create complex forms in our applications. The advantages of its use that we could see with this example are:
- Less code
- Easy validation
- Some validations are pre-defined in the library
- If you put a print on the Flutter form build method you will see that the view is repainted every time user enters a character on a TextFormField. On the other hand in the reactive form, this doesn’t happen in any widget.
- Also profiling you can see that the reactive version is more optimal than the native one
Also, other advantages of using reactive_forms are:
- A high amount of Reactive Widgets that can be used (see here)
- Code generator for generating (read more)
- Imagine you have a field like a phone number and a person can have more than one so you need to repeat the same field several times and store the data on an array. Well with reactive forms this is a piece of cake 🍰 if you use FormArray.
- Imagine you have a form divided into several views 🤯 (like an onboarding carousel) and you need to submit the data at the end. With reactive form is also very easy to do this.
I won’t say more 🤗. Just encourage you to read the docs and give it a chance.
You can FIND THE CODE HERE.
Also if you found this helpful please give me a clap 👏. This is my first post so any feedback positive or negative that you can give me will be very well appreciated.
Until the next one: keep improving! The limit is your imagination!!