I am yet to see an Angular application without some kind of a form. The power of Internet two is the ability to create user content and express ourselves. Nothing of that could happen without the communication between the front end and the back end technologies.
I am not going to talk about protocols, network or REST. I am going to dive a little bit into the ways of Angular to collect the information.
Two ways to do it - template driven and reactive forms.
I am talking about Angular Reactive forms today.
- The name “template driven” forms comes from the way they are structured. It follows a declarative approach where the form itself and the validations are defined in the HTML.
- Reactive forms take a more programmatic approach, where you validate and define using TypeScript.
- Template driven forms use Two-way data binding to communicate with their “model”
- Reactive forms use form controls that are treated as streams of data - aka. Observables that can be observed and reacted upon.
- Compared to Reactive forms, you have limited control with Template driven forms.
How do I prefer to use them?
I find template driven forms useful in controlling the UI ( like a checkbox for example ). Conditional rendering based on some specific input.
Less complex forms, although I am starting to switch to “Always reactive forms”.
Reactive forms are easier to work with. Even though the set up is heavier and the complexity is a little bit more, Angular reactive forms are way too powerful and have to offer so much.
Another thing I like more about Reactive forms is they tend to be more “structured”. It is strict and maintainable. I don’t have to look in the entire HTML template in order to find all I want.
Controlling the entire form in the component class is just great. This is the way it should be.
In order to use the reactive forms you have to set up the module and import the dependencies.
It is done through the ReactiveFormsModule from the @angular/forms. This provides all the necessary classes and functions for our reactive forms to work.
With this we will have the option to use some special binding such as formGroup, formGroupName, ngSubmit and more.
One of the most important classes I am going to import is the FormBuilder. A class that comes with great features:
- control () - you can create individual form control. It returns a FormControl
- group () - this is the main method to create the form group.An object that utilizes the keys as form control names. It returns a FormGroup
- array () - A method that returns a FormArray instance. Incredibly powerful
You can even nest FormGroups!
But what exactly is Form Control and Form Groups?
This is the building block of reactive forms. It represents an individual input field within the form and tracks its value, validation status and every used interaction.
One thing I want to mention is that FormControl is a class that extends AbstractControl.
We bind it to the template with the formControlName and use the correlated name or we just provide the entire control. It goes directly to the input element.
Some useful methods I want to present to you are:
- valueChanges - observable that fires every time a value is changed
- setValue - sets a new value for the form control
- patchValue - it acts the same as setValue when it comes to FormControls
- updateOn - FormHooks that represents the update strategy
- setValidators, removeValidators - useful methods to control the validators of the FormControl
While FormControl represents an individual input field, FormGroup allows you to group related form controls together. It allows you to manage the state, validation and values as a single entity.
It is way easier to keep track of the validity of the entire form you have.
How does it do it?
While we instantiate the new FormControl we can provide some arguments in the constructor. One of them is the ValidatorFn. A function that receives a control and synchronously returns a map of validation errors if present, otherwise null.
A helper class provided by the Reactive Forms module that simplifies the entire process of building the form.
It offers declarative ways to build complex forms.
The most important method here is the group - accepts an object which contains all the keys and corresponding inner control types.
One other great feature is that we can dynamically create and modify form controls!
Reactive forms just shine here!
Let’s say we are building a form that needs to be dynamic. We need an address, but we are not sure how many addresses people have. What is the solution?
We allow multiple ones.
But how do we do it if we said we define the form itself in the FormBuilder.
Easy. We use the power of arrays. FormArrays!
That’s a class that represents an array of multiple FormGroups or FormControls. It also provides methods to add or remove such.
The initial setup could be a little tricky if you are doing it for the first time. I remember it was a little bit confusing when I was trying to do it.
We add controls with the push() method and removeAt() to .. well… to remove.
console.log(address.at(0).value); // Access the value of a specific control
Let’s show the flow of creating everything in images. I guess it’s going to be useful to visualize it.
- we import the reactive form module
- define the form builder
- create the form group
- set up arrays ( if any )
- bind to the HTML
- control the events and submission
If you already follow me, you know there would be a repo with the code.
Have a look here.
You can check a custom Validation function, set up based on my preferred Angular application structure and more.
Don’t forget to “star” the project. It would be awesome!
Reactive forms are the best way to handle complex logic and data.
It’s my preferred way of creating user interactions. Although I sometimes use template driven forms, it’s on very rare occasions.
Reactive forms are dynamic, reactive ( I know, I know ) and more declarative.
Play around and find out!