Overview of Forms in Angular
This guide explains the key differences between Template-Driven Forms and Reactive Forms in Angular.
Feb 20, 2019 • 8 Minute Read
Introduction
Forms in Angular enable users to work with user inputs like login, register, save, update, and many other data entry tasks.
There are two ways through which we can handle user inputs in Angular: reactive forms and template-driven forms. Both capture user input events from the view, validate the user input, create a form model and data model to update, and provide a way to track changes.
Reactive Forms
Reactive forms are more scalable, testable, reusable, and robust. If you build applications which involve more reactiveness, then use reactive forms of Angular to build applications.
Let's consider an example where we are setting up the Reactive form using the form model FormControl instance.
Filename: example.component.ts
import { Component } from '@angular/core';
import { FormControl } from '@angular/forms';
@Component({
selector: 'app-reactive-example',
template: `
Example input: <input type="text" [formControl]="exampleControl">
`
})
export class ExampleComponent {
exampleControl = new FormControl('');
}
Template-Driven Forms
Template-driven forms are not as scalable as Reactive forms. If you want a very basic form requirement and logic that can be managed solely in the template, use template-driven forms.
Let's consider an example for a template-driven form where we are binding the text value exampleText to the input element.
Filename: example.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-template-example',
template: `
Example Text: <input type="text" [(ngModel)]="exampleText">
`
})
export class ExampleComponent {
exampleText = '';
}
From this guide, you will be able to identify which form type to choose based on your requirement.
Key Differences Between Reactive Forms and Template-Driven Forms:
-
The data model in reactive forms is more structured than template-driven forms.
-
Reactive forms are synchronous in nature, whereas template-driven forms are asynchronous.
-
Form validations in reactive forms are handled through functions, whereas in template-driven forms they are handled through directives.
-
Reactive forms are immutable in nature, whereas template-driven forms are mutable.
-
Reactive forms are more explicit and created in the component class and template-driven forms are less explicit and created by directives.
Building Blocks of Angular Forms
-
FormControl control instance tracks the value and validation status of an individual form control.
-
FormGroup control instance tracks the same values and status for a collection of form controls.
-
FormArray control instance tracks the same values and status for an array of form controls.
-
ControlValueAccessor control instance creates a bridge between Angular FormControl instances and native DOM elements.
Forms in Angular use a form model to keep track of value changes between Angular forms and form input elements.
Data Flow in Angular Forms
Data flow in Angular is handled differently in both the reactive and template-driven forms.
The data flow examples below begin with the example text input field example from above, and then show how changes to example text are handled in reactive forms compared to template-driven forms.
Data Flow in Reactive Forms
Updates or changes from the view (or DOM) to the model and from the model to the view are synchronous and aren't dependent on the UI rendering. In reactive forms, each form element in the view is directly linked to a form model (FormControl instance).
Let's consider an example shown below and go through the steps of data flow in reactive forms.
Filename: example.component.ts
import { Component } from '@angular/core';
import { FormControl } from '@angular/forms';
@Component({
selector: 'app-reactive-example',
template: `
Example input: <input type="text" [formControl]="exampleControl">
`
})
export class ExampleComponent {
exampleControl = new FormControl('');
}
The steps below outline the data flow from view to model.
- The user types a value into the input element, in this case, the text value says "Hello World".
- The form input element emits an "input" event with the latest value.
- The control value accessor listening for events on the form input element immediately relays the new value to the FormControl instance.
- The FormControl instance emits the new value through the valueChanges observable.
- Any subscribers to the valueChanges observable receive the new value.
The steps below outline the data flow from model to view.
- The user calls the exampleControl.setValue() method, which updates the FormControl value.
- The FormControl instance emits the new value through the valueChanges observable.
- Any subscribers to the valueChanges observable receive the new value.
- The control value accessor on the form input element updates the element with the new value.
Data Flow in Template-Driven Forms
In template-driven forms, each form element is linked to a directive that manages the form model internally.
Let's consider an example shown below and go through the steps of data flow in template-driven forms.
Filename: example.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-template-example',
template: `
Example Text: <input type="text" [(ngModel)]="exampleText">
`
})
export class ExampleComponent {
exampleText = '';
}
The steps below outline the data flow from view to model.
- The user types "Hello World" into the input element.
- The input element emits an "input" event with the value "Hello World".
- The control value accessor attached to the input triggers the setValue() method on the FormControl instance.
- The FormControl instance emits the new value through the valueChanges observable.
- Any subscribers to the valueChanges observable receive the new value.
- The control value accessor also calls the NgModel.viewToModelUpdate() method which emits an ngModelChange event.
- Because the component template uses two-way data binding for the exampleText property, the exampleText property in the component is updated to the value emitted by the ngModelChange event.
The steps below outline the data flow from model to view.
- The exampleText value is updated in the component.
- Change detection begins.
- During change detection, the ngOnChanges lifecycle hook is called on the NgModel directive instance because the value of one of its inputs has changed.
- The ngOnChanges() method queues an async task to set the value for the internal FormControl instance.
- Change detection completes.
- On the next tick, the task to set the FormControl instance value is executed.
- The FormControl instance emits the latest value through the valueChanges observable.
- Any subscribers to the valueChanges observable receive the new value.
- The control value accessor updates the form input element in the view with the latest exampleText value.
Form Validation in Angular
Validation is one of the important parts of forms for security and other reasons. Angular provides a set of built-in validators as well as the ability to create custom validators.
- In reactive forms, validations are handled through custom validators as functions that receive control to validate.
- In template-driven forms validations are handled through directives and must provide custom validator directives that wrap validation functions.
Conclusion
In this guide, we have explored the forms in angular and we saw different types of forms like reactive and template-driven forms.
You can learn more about Angular in my guide Angular Data Binding Overview.