Introduction to Angular Reactive Forms

It is hard to think about any customer-facing application without at least one form. From the developer's standpoint, forms are a critical part of an application; they allow us to get input information that we can process and store. From the user's point of view, forms are an interface that will enable us to input data; they must be neat and clear. On more than one occasion, I have not bought a product or a service because a form in the checkout process was broken; a broken form can lead to conversion losses.

The Angular framework provides developers two ways to create forms: Template Driven Forms and Reactive Forms. If you come from the first version of the Angular framework, you will be very familiar with Template Driven Forms where two-way binding predominate. Reactive Forms is a new approach that empowers developers and gives more programmatic control over the form definition and validations.

Template Driven Forms Reactive Forms
Use case Simple scenarios Complex scenarios where validations could change while user input data or input controls will change dynamically (controls can be added, removed, disabled).
Construction In HTML templates In Components or Service classes
Biding Two way data biding: tracks changes in model and form Immutable model

Build a Reactive Form

The API has three main classes that are our building blocks to construct a form. All of these extend the AbstractControl Class, which holds a lot of handy properties and functions. In the class diagram that follows you can see these three classes and some of the properties and methods they share. This diagram doesn't show a complete list of the methods available, the purpose of the diagram is just to make you aware of the main classes available to build a form, the relations and commonalities between them.

Class Description Use case
FormControl This represents a single control such as an input text field or a radio button. Use FormControl to create a single input field. If we were talking about a user registration form name, user, a slider to accept notifications would be FormControl instances.
FormGroup This represents a group of controls, in fact your form is actually an instance of FormGroup that could be composed of a bunch of FormControl, FormGroup or FormArray instances. Use FormGroup to declare you form in the component or service class, you should also use this class to group related form controls such as the input fields required for an Address: address, city, state, etc.
FormArray This represents a collection of controls (Controls that extends AbstractControl class). This means that in the array you could have a FormGroup, a FormControl or another FormArray but the most common use is having similar elements in the array. Use FormArray to handle controls or form groups that could be added or removed by the user. For example talking about a registration form we could use the FormArray for a list of emails (represented by a FormControl) or a list of addresses (represented by a FormGroup).

If you have experience working with AngularJS you will realise that a lot of properties these classes have come from the first version of Angular such as: dirty, pristine, touched and valid so you may already know them. Here is a list of the most common functions and properties I use when building a reactive form.

Properties

  • dirty: Boolean that indicates if the form or control has been modified by the user. (True if has been modified)
  • pristine: Boolean that indicates if control of form has not been modified by the user. (True if not has been modified)
  • touched: Boolean that indicates if control has been touched, a control has been touched if it got the focus despite if the user input something or not.
  • valid: Boolean that indicates if the form or control is valid.

*If you think the dirty, pristine, touched and valid concepts are not clear, this codepen from the Angular 1.X version could help while you play around with a real form. Angular 1.x Form Code Pen

Methods

  • setValue: Will set a new value for the control. In the case of formGroup all the values must be set if not an error will be thrown, also the object that has the values must not have properties that does not exist in the FormGroup.

  • patchValue: Will set a new value for the control, this method will iterate through the all the child controls inside a control and call the method patchValue. The benefit of patchValue is that you can set values to a formGroup partially, this means that you can set values using an object that does not have all the values for the control (Or maybe the object has some other values that are not defined in the control, these will be ignored).

  • setValidators: Allow to set new validators form a control, it is very helpful when you need to set new validators depending on a condition, for example a slide button that has been changed by the user. *If the valid status must be updated right after this updateValueAndValidity must be called.

  • clearValidators: Removes sync validators, helpful to remove validators given a certain condition. *If the control has Async validators, this should ve removed with If the valid status must be updated right after this you should call updateValueAndValidity.

  • clearAsyncValidators: Removes async validators, if the valid status must be updated right after this updateValueAndValidity must be called.

  • updateValueAndValidity: This function will update value and validators after you have played clearing or adding validatros programatically.

  • markAsTouched: Will change the touched status property to true in a control, usefull for cases where an error must be displayed but the control has not been touched yet.

Notes

  • FormGroup, FormArray and FormControl classes extend the AbstractControl class so you have a common bunch of properties and functions available to play.
  • Remember that each control you have should have formControlName property in your template.
  • It is not necessary to use the name property when creating the form template.

Angular Forms sample

You can build Angular Reactive Forms without the need of any additional css/html library or framework. You can give your forms a custom look & feel just by writting some CSS from scratch or you good go the other way and use something that is ready such as frontend frameworks like Bootstrap, Angular Material components, Kendo UI components, etc.

For this example I will be using Angular Materia to build the following Form

The source code for this sample can be find on my github repo: here