1. Angular Reactive Forms & Validations in Reactive Forms

Erdener Ünal
Beyn Technology
6 min readJan 28, 2022

--

I believe that form handling (track, update, validate, etc.) is one of the significant topics in Frontend Development. The reason why it is important is that it is a subject, you can encounter in almost every project. Think that we have a form that we have to deal with. We should bind data to our application that we send to the backend. What options does Angular offer us for this procedure? Let’s examine these options and the powerful form structures of Angular.

Table of Contents

  1. Angular Form Structure Options
  2. How to Implement Reactive Forms in Our Project?
  3. Elementary Built-in Classes of Reactive Forms
  4. FormBuilder Service
  5. Validations in Reactive Forms
  6. An Example for Review

Angular Form Structure Options

Angular team provides us with two different form structures to handle our forms:

  • Template-Driven Forms
  • Reactive (Model-Driven) Forms

Template-Driven forms have an easy-to-use structure that enables us to track data with the help of directives such as ngModel. These forms can be used where we have lower form requirements. These forms have a more implicit structure and work async.

Reactive Forms follow a model-driven approach to handle form input whose values can be changed over time. Reactive forms are handled by component (.ts) rather than by the template side. These forms are easy to test and validate.

Elementary differences of Reactive forms and Template-driven forms

How to Implement Reactive Forms in Our Project?

First, We need to import ReactiveFormModuleto our app module.

We must import ReactiveFormsModule from @angular/forms

Elementary Built-in Classes of Reactive Forms

You should now some certain structures to comprehend reactive forms. The first and primary part of reactive forms is FormControl.

Creating a simple FormControl class

It creates a new class, watches a specific input and it keeps its values and validations. It takes two parameters. The first one is the default value of input (input, checkbox, radio button, etc.). The second is a list of sync validations of input. And third is for async validations arguments.

FormGroups are used to group FormControls and keep their values and validation status. We should bind our form template by using [formGroup] attribute. formControlName links each input to our FormGroup.

Creating and binding FormGroups to our app.

FormArrays are a wrapper as FormGroups. It collects FormControl values and validation statuses in an array. It is used when the number of form elements is not certain. In some cases, the user can add or delete form fields or we may want to change the number of fields concerning some conditions. In such circumstances, it is good to use FormArrays. We will discuss this topic in more detail in my next article by using examples.

ControlValueAccessor creates a communication channel between FormControl and native DOM element on the template side. It provides us to write new values and watch changes in FormControl’s value. It will be detailed in my next article when I mention Dynamic Forms.

FormBuilder Service

In larger forms, using more FormControl and FormGroup constructors may cause complicated form structures. To prevent these complications, we can use a built-in helper FormBuilder service.

Implementing FormBuilder service to our component

Validations in Reactive Forms

One of the strongest aspects of reactive forms is validation processes. Reactive forms have a synchronized structure. In this way, validation processes and value tracking provide much more accurate results. Validation type can be sync or async.

Sync Validators

Sync validator can provide fast and reactive functions. It returns an error object or null. If you do not have backend requirements, these validators will suffice for you. These validators are answers fast, so react value changes immediately.

To use validation operations, we should import Validators class from @angular/forms.

As I said before, in form controls, the first parameter is for the initial value, second and third parameters are for validators. Validators class contains some built-in validation operators such as ;

  • required: It controls if the form input is empty or not.
  • min-max: It checks whether the input value is less — greater than the specified values.
  • minLength — maxLength: It checks whether the input character number is less — greater than the specified values.
  • pattern: It controls the form input according to a certain regex pattern.
  • email: It checks the input is in a valid email format.

When we bind the validations to FormControls, each validator returns null if a field is valid. Otherwise, it returns an object key with boolean true.

Async Validators

On the other hand, async validators are promise or observer-based validators. It can handle if we should some backend controls as HTTP requests. At this point, it should be noted that async validators must return a promise or an observable. These validators implement two interfaces ; AsyncValidator and AsyncValidatorFn . AsyncValidatorFn takes a control and returns a promise-observable or null. AsyncValidator is an interface that is extended from Validator. Async validators work after all sync validators are performed.
It prevents unexpected or unwanted side effects and performance issues.

An Example for Review

Let’s create an example scenario to simulate details. We have a registration form that contains username, email, and password fields. But there are some specifications about these fields. First, all fields must be required to submit. Password must be at least six and at most twenty-five characters. Email must be in a valid email format. Finally, let's say username cannot contain “0”.

Implementing Validators and using built-in control keys

Built-in validators worked well in most parts. But we must check the username format is valid for our rules. To perform this control, we have to create a custom validator.

Creating a Sync Custom Validator

Creating custom validator function and implementing that to our component
Visual demonstration of our example form

Creating an Async Custom Validator

Let’s say in this registration form, we want email addresses to be unique. To provide this control, we should send an HTTP request to the backend and check our database. In such cases, async validators meet our validation needs. First, we should create a fake API to demonstrate an HTTP request.

Creating custom async validator function and implementing that to our component

To provide reusability, we can create a custom validator class as above. In this case, our validator class has a method createAsyncValidatorthat will provide validation operation. We pass our fake service as an argument and it returns ValidationErrors as Observable or null.

Finally, we should add our async validator to our email form control as we did sync validator.

Updating Form Values

In some cases, we may want to update or reset our form values. There are several ways to perform these operations:

  • setValue: If we want to update all fields of forms, this method should be used.
  • patchValue: If some part of the forms will be changed, it provides us to update the form partially.
  • reset: It is used for resetting form fields.
Using of update methods

To sum up, When we develop a frontend project, we need to utilize the whole capacity of the framework we use. Angular offers us a very powerful form control mechanism: Reactive Forms. In this article, I aimed to show you elementary parts of reactive forms and how to use reactive forms with a basic example. In addition, I wanted to show validation methods and how to add custom validators in form fields. I hope I reach my goal in this article and make some concepts easier for you to understand. In my next article, we will examine dynamic reactive form creation using FormArrayand ControlValueAccessorin more detail.

May the coding with you!

--

--