Reactive forms are just opposite to what do in template driven forms. This means that instead of defining the form and its controls in the template, we define the form structure in our code.
We can say that the Reactive forms are model-driven approach in contrast to template-driven approach. We have total control on forms, controls and their validations.
Note: This chapter is strictly in continuation to previous chapter : Angular Forms : Template Driven. Please go through the previous chapter before reading this one.
Difference between template-driven and reactive forms
Template driven Form
<form>
<input name="uname" ngModel>
<input name="age" ngModel>
</form>
In template driven forms, ngForm directive is implicitly created and with ngModel its child directives are implicitly created as well. So the following classes gets instantiated implicitly.
- FormGroup
- FormControl 1
- FormControl 2
Reactive Form
<form [formGroup]="form">
<input formControName="uname">
<input formControName="age">
</form>
While in Reactive forms we need to provide the Form structure in the code. We need to instantiate a form with a FormGroup class and controls with FormControl class.
form = new Form({
uname: new FormControl(),
age: new FormControl()
});
Re-implementing "Movie Booking" app in Reactive way
With this understanding, we will now implement the previously created "Movie Booking" form in Reactive way. I will be pointing out the necessary changes that needs to be done from the previous example.
Change "FormsModule" to "ReactiveFormsModule"
import { ReactiveFormsModule } from '@angular/forms';
...
...
@NgModule({
imports: [BrowserModule, ReactiveFormsModule],
declarations: [App],
bootstrap: [App]
})
Import Anguar Forms classes
In "bookMovie.component.ts", import the following classes from @angular/forms
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
Change Form tag attributes
In "bookMovie.component.ts", change the form tag attributes as:
<form (ngSubmit)="onSubmit(bookMovieForm)" [formGroup]="bookMovieForm">
Note that we are referencing formGroup variable in the template as bookMovieForm, so that its child controls can be accessed.
Change input tags
In "bookMovie.component.ts", change the first input tag and its error message tag as:
<input type="text" class="form-control" formControlName="uName">
<div class="alert alert-danger" [hidden]="bookMovieForm.controls.uName.valid">User name is required</div>
Note that we have removed -> ngModel data binding and required attribute as we did in template driven forms. Also, the child control model is now accessed with form's controls object : bookMovieForm.controls.uName
Now, repeat this change for other subsequent controls.
Build Form using Angular FormBuilder
In "bookMovie.component.ts", build the form using FormBuilder as follows:
constructor(private formBuilder: FormBuilder) { }
ngOnInit() {
...
...
this.bookMovieForm = this.formBuilder.group({
uName: [this.uName, Validators.required],
name: [this.model.name, Validators.required],
cinemaHall: [this.model.cinemaHall , Validators.required],
timing: [this.model.timing, Validators.required]
});
}
Here, we have injected instance of FormBuilder class and used this to instantiate form along with child controls through code.
Now we have converted our template driven app to reactive app. So these are the changes you can keep in your mind to decide whether to go for template driven forms or reactive forms in your Angular application.
Live Code
You can access the full live source code here - Angular Reactive forms