Angular is a popular front-end framework made by Google. Like other popular front-end frameworks, it uses a component-based architecture to structure apps.
In this article, we’ll look at the basics of creating forms with Angular.
Different Kinds of Forms
Angular provides 2 different approaches to handling user input through forms.
They are either reactive or template-driven. They both capture events from the view, validate their user input, and create a form model and data model to update, and provide a way to track changes.
Reactive forms are more robust. They’re more scalable, reusable and testable.
Template-driven forms are useful for adding a simple form to an app. They’re easy to add, but they don’t scale as well as reactive forms.
Common Foundation
Both kinds of forms share the following building blocks:
FormControl— tracks the value and validation status of individual form controlsFormGroup— tracks the same value and status for a collection of form controlsFormArray— tracks the same value and status for an array of form control.s.ControlValueAccessor— creates a bridge between AngularFormControlinstances and native DOM elements.
Form Model Setup
We can set up the form model of a Reactive form by setting the formControl property of an input element.
For example, we can write the following code:
app.module.ts :
import { BrowserModule } from "@angular/platform-browser";
import { NgModule } from "@angular/core";
import { ReactiveFormsModule } from "@angular/forms";
import { AppComponent } from "./app.component";
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule, ReactiveFormsModule],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {}
app.component.ts :
import { Component } from "@angular/core";
import { FormControl } from "@angular/forms";
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
nameControl = new FormControl("");
}
app.component.html :
<input type="text" [formControl]="nameControl" />
In the code above, we added the ReactiveFormsModule to our AppModule .
Then we created nameControl in AppComponent .
Finally, we set the formControl property to nameControl to connect the input to the FomControl .
Setup in Template-Driven Forms
We can use the ngModel directive to bind our input value to the a field in our component.
For example, we can write the following:
app.module.ts :
import { BrowserModule } from "@angular/platform-browser";
import { NgModule } from "@angular/core";
import { FormsModule } from "@angular/forms";
import { AppComponent } from "./app.component";
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule, FormsModule],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {}
app.component.ts :
import { Component } from "@angular/core";
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
name: string;
}
app.component.html :
<input type="text" [(ngModel)]="name" />
In the code above, we imported the FormsModule in app.module.ts .
Then we created the name field in AppComponent to bind the data to the field.
Then we bind our input’s value to name via ngModel .
Both Reactive and Template-Driven forms provide 2 way binding between the model and the input.
Data Flow in Reactive Forms
From view to model, the data flow follows the following steps:
- User types something into the input
- Form input emits an input event
- Control value accessor listens for events on the form input and sends the new value to the
FormControlinstance. - The
FormControlinstance emits the new value through thevalueChangesobservable. - Subscribes to
valueChangesreceive the new value
From model to view, the flow is as follows:
- The user calls the
nameControl.setValuemethod to update theFormControlvalue - The
FormControlinstance emits the new value through thevalueChangesobservable. - Any subscribers to the
valueChangesobservable 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
The data from the view to the model in template-driven forms are as follows:
- User types something into the input element.
- The input element emits an input event with the value typed in
- The control value accessor attached to the input triggers the
setValuemethod on theFormControlinstance - The
FormControlinstance emits the new value throughvalueChangesobservable - Any subscribers to the
valueChangesobservable receives the new value - The control value accessor also calls
NgModel.viewToModelUpdatemethod which emits anngModelChangeevent ngModelChangestriggers model value update
From model to view, the flow is as follows:
- The value is updated in the component
- Change detection begins
ngOnChangesis called on theNgModeldirective instance because the input value has changedngOnChangesqueues an async task to set the value of theFormControlinstance- Change detection completes
- The task to set
FormControlinstance value is run on next tick FormControlinstance emits the latest change through thevalueChangesobservable- Any subscribers to the
valueChangesobservable receives the new value - Control value accessor updates the form input element in the view
Conclusion
We can create Angular forms as Reactive or Template-Driven forms.
Reactive forms are more robust and Template-Driven forms are suitable for simple forms.
They both have the same parts. The control value accessor takes the input value and sets it to the model.