In this post we’ll see how to build a reactive form in Angular which is also known as Model-driven form.
- Interested in creating a template-driven form refer this post- Angular Template-Driven Form Example
Importing ReactiveFormsModule
You need to import ReactiveFormsModule into the AppModule (app.module.ts) for Angular Reactive form to work. Add ReactiveFormsModule in the imports section of the AppModule.
imports: [ BrowserModule, ReactiveFormsModule ],
Reactive Form example Application in Angular
In the example we’ll create a form with two input fields for name and email, a date picker for picking date and a drop down to select one of the option. Once finsihed our form should look something like this-
Data Model
Member class defines the data model reflected in the form.
member.model.ts
export class Member { name: string; mail: string; membershipDate: Date; membershipType: string; constructor(name: string, mail: string, membershipDate: Date, membershipType: string) { this.name = name; this.mail = mail; this.membershipDate = membershipDate; this.membershipType = membershipType; } }
Component class (app.component.ts)
In ReactiveForm you create the form controls in the Component class which you will sync up with the corresponding template.
To create Angular Reactive form you will mainly use FormControl, FormGroup and FormArray classes. A FormControl represents an individual form control where as FormGroup represents a collection of form controls as a group. So, it is obvious that in your code you will create a FormGroup object and with in that you will add form controls corresponding to fields in the form.
import { DatePipe } from '@angular/common'; import { Component, OnInit} from '@angular/core'; import { FormControl, FormGroup} from '@angular/forms'; import { Member } from './member.model'; @Component({ selector: 'app-root', templateUrl: './app.component.html', providers: [DatePipe] }) export class AppComponent implements OnInit { membershiptypes = ['Silver', 'Gold', 'Platinum']; currentDate = new Date(); member = new Member('', '', new Date(), ''); submitted = false; membershipForm : FormGroup; constructor(private datePipe: DatePipe){ } ngOnInit() { this.membershipForm = new FormGroup({ memberName: new FormControl(null), email: new FormControl(null), mdate: new FormControl(this.datePipe.transform(this.currentDate, 'yyyy-MM-dd')), membershipType: new FormControl('Silver') }); } onSubmit(){ this.submitted = true; this.member.name = this.membershipForm.value.memberName; this.member.mail = this.membershipForm.value.email; this.member.membershipDate = this.membershipForm.value.mdate; this.member.membershipType = this.membershipForm.value.membershipType; } }
Important points to note here are-
1. You need to import FormControl and FormGroup classes.
2. A reference to FormGroup is created named membershipForm.
3. Using that reference a new FormGroup object is created and an array of form controls are added to that FormGroup object.
4. A FromControl takes three arguments state, Validator and AsyncValidator. In this example we are not going into validation so we’ll pass just one argument. For name and email initial value is passed as null. For date current date is passed as default and for Membership type ‘Silver’ is passed as default. For validation in reactive form check this post- Angular Reactive Form Validation Example
5. onSubmit() method is called when the form is submitted and the values entered in the form are used to create an object of Member class.
Template (app.component.html)
<div class="container"> <div class="row"> <div class="col-xs-12 col-sm-10 col-md-8"> <h1>Membership Form</h1> <form [formGroup]="membershipForm" (ngSubmit)="onSubmit()"> <div class="form-group"> <label for="name">Name</label> <input type="text" class="form-control" id="name" formControlName="memberName"> </div> <div class="form-group"> <label for="email">email</label> <input type="email" class="form-control" id="email" formControlName="email"> </div> <div class="form-group"> <label for="mdate">Membership Date</label> <input type="date" class="form-control" id="mdate" formControlName="mdate"> </div> <div class="form-group"> <label for="type">Membership Type</label> <select class="form-control" id="type" formControlName="membershipType"> <option *ngFor="let mtype of membershiptypes" [value]="mtype">{{mtype}}</option> </select> </div> <button type="submit" class="btn btn-success">Submit</button> </form> </div> </div> <hr> <div *ngIf="submitted"> <div class="row"> <div class="col-xs-12 col-sm-10 col-md-8"> <p>Name: {{member.name}}</p> <p>email: {{member.mail}}</p> <p>Membership Date: {{member.membershipDate | date:'dd/MM/yyyy'}}</p> <p>Membership Type: {{member.membershipType}}</p> </div> </div> </div> </div>
Important points to note here are-
1. You need to tell the template, from where it has to get all the FormControls for the form, that is done by binding the FormGroup reference.
<form [formGroup]="membershipForm" (ngSubmit)="onSubmit()">
2. For syncing up the form controls you will have to bind each form field with the form control created in the component. That is done by assigning formControlName to the name given in the component.
<input type="text" class="form-control" id="name" formControlName="memberName">
3. For Membership Type dropdown, options are added using ngFor which iterates over an array called membershiptyes defined in the Component class.
4. Submit button is of type submit so it will trigger a submit event for that event binding is done at the form level.
<form [formGroup]="membershipForm" (ngSubmit)="onSubmit()">
5. There is another row which just displays the entered values after the form is submitted. There is a 'submitted' field which is assigned value true in the onSubmit() method.
That's all for this topic Angular Reactive Form Example. If you have any doubt or any suggestions to make please drop a comment. Thanks!
>>>Return to Angular Tutorial Page
Related Topics
You may also like-
Not Working In angular 13.
ReplyDeleteERROR Error: Uncaught (in promise): NullInjectorError: R3InjectorError(BaseModule)[DatePipe -> DatePipe -> DatePipe -> DatePipe]:
ReplyDeleteNullInjectorError: No provider for DatePipe!
NullInjectorError: R3InjectorError(BaseModule)[DatePipe -> DatePipe -> DatePipe -> DatePipe]:
NullInjectorError: No provider for DatePipe!
at NullInjector.get (core.mjs:11145:1)
at R3Injector.get (core.mjs:11312:1)
at R3Injector.get (core.mjs:11312:1)
at R3Injector.get (core.mjs:11312:1)
at NgModuleRef.get (core.mjs:21872:1)
at R3Injector.get (core.mjs:11312:1)
at NgModuleRef.get (core.mjs:21872:1)
at Object.get (core.mjs:21549:1)
at lookupTokenUsingModuleInjector (core.mjs:3358:1)
at getOrCreateInjectable (core.mjs:3470:1)
at resolvePromise (zone.js:1211:1)
at resolvePromise (zone.js:1165:1)
at zone.js:1278:1
at _ZoneDelegate.invokeTask (zone.js:406:1)
at Object.onInvokeTask (core.mjs:25579:1)
at _ZoneDelegate.invokeTask (zone.js:405:1)
at Zone.runTask (zone.js:178:1)
at drainMicroTaskQueue (zone.js:585:1)
at ZoneTask.invokeTask [as invoke] (zone.js:491:1)
at invokeTask (zone.js:1648:1)
defaultErrorLogger @ core.mjs:6485
handleError @ core.mjs:6532
next @ core.mjs:26158
next @ Subscriber.js:91
_next @ Subscriber.js:60
next @ Subscriber.js:31
(anonymous) @ Subject.js:34
errorContext @ errorContext.js:19
next @ Subject.js:27
emit @ core.mjs:22467
(anonymous) @ core.mjs:25618
invoke @ zone.js:372
run @ zone.js:134
runOutsideAngular @ core.mjs:25491
onHandleError @ core.mjs:25618
handleError @ zone.js:376
runGuarded @ zone.js:147
api.microtaskDrainDone @ zone.js:1072
drainMicroTaskQueue @ zone.js:592
invokeTask @ zone.js:491
invokeTask @ zone.js:1648
globalCallback @ zone.js:1679
globalZoneAwareCallback @ zone.js:1712
If it is a DatePipe problem then ensure that it is added in providers section of Component
Deleteproviders: [DatePipe]
Refer AppComponent code. You can also add it in the providers section of app.module.ts