In this article, I will guide you about reactive forms. When to use reactive forms? And features of reactive form also show some example of reactive forms.
If forms are very important for your app, or reactive pattern are used in your app, you should use reactive forms.
Note:if your using reactive form also import FormModule and ReactiveFormModule in appmodule or specific component module.
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, FormModule, ReactiveFormsModule, ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
Form With FormGroup Characteristic:
export class FormComponent { profileForm = new FormGroup({ email: this.emailFormControl, firstName: new FormControl(''), lastName: new FormControl(''), address: new FormGroup({ street: new FormControl(''), city: new FormControl(''), state: new FormControl(''), zip: new FormControl('') }) }); }
Output with Json Format
{ email: '', firstName: '', lastName: '', address: { street: '', city: '', state: '', zip: '' } }
The FormBuilder service is an injectable provider that is provided with the reactive forms module. form builder is a service that does the same things as form-group, form-control and form-array. FormBuilder is a service that is trying to help us reduce boiler-plate code. there is no technical advantage and whichever code you use all boils down to your preference.
Form with FormBuilder Characteristic:
export class FormComponent { constructor(private fb: FormBuilder) { } profileForm = this.fb.group({ email: this.emailFormControl, firstName: [''], lastName: [''], address: this.fb.group({ street: [''], city: [''], state: [''], zip: [''] }), }); }
Output with Json Format
{ email: '', firstName: '', lastName: '', address: { street: '', city: '', state: '', zip: '' } }
In which scenarios we can use formgroup or formbuilder?
when our data is dynamic. we should use formbuilder instead of formGroup. because it reduce code boilerplate. and we don't need to write it manually formcontrols.
<form [formGroup]="singUpForm" (ngSubmit)="onSubmit()"> <p> <label for="firstname">First Name </label> <input type="text" id="firstname" name="firstname" formControlName="firstname"> </p> <p> <label for="lastname">Last Name </label> <input type="text" id="lastname" name="lastname" formControlName="lastname"> </p> <p> <label for="email">Email </label> <input type="text" id="email" name="email" formControlName="email"> </p> <p> <label for="gender">Geneder </label> <input type="radio" value="male" id="gender" name="gender" formControlName="gender"> Male <input type="radio" value="female" id="gender" name="gender" formControlName="gender"> Female </p> <p> <label for="country">country </label> <select id="country" name="country" formControlName="country"> <option value="1">India</option> <option value="2">USA</option> <option value="3">England</option> <option value="4">Singapore</option> </select> </p> <p> <button type="submit">Submit</button> </p> </form> import { Component } from '@angular/core'; import { FormGroup, FormControl, Validators } from '@angular/forms' @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'AngularForm'; contactForm = new FormGroup({ firstname: new FormControl(), lastname: new FormControl(), email: new FormControl(), gender: new FormControl(), country: new FormControl() }) onSubmit() { console.log(this.contactForm.value); } }
contactForm = new FormGroup({ firstname: new FormControl('',Validators.required]), lastname: new FormControl('',Validators.required]), email: new FormControl('',Validators.required]), gender: new FormControl('',Validators.required]), country: new FormControl('',Validators.required]) }) //new FormControl('',Validators.required]), first parameter is default value. which is empty string. and second parameter is validation.
<form [formGroup]="myForm" (ngSubmit)="onSubmit(myForm)"> <div> <label> Name: <input formControlName="name" placeholder="Your name"> </label> </div> <div> <label> Email: <input formControlName="email" placeholder="Your email"> </label> </div> <div> <label> Message: <input formControlName="message" placeholder="Your message"> </label> </div> <button type="submit">Send</button> </form> import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormGroup } from '@angular/forms'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit { myForm: FormGroup; constructor(private fb: FormBuilder) {} ngOnInit() { this.myForm = this.fb.group({ name: '', email: '', message: '' }); } onSubmit(form: FormGroup) { console.log('Valid?', form.valid); // true or false console.log('Name', form.value.name); console.log('Email', form.value.email); console.log('Message', form.value.message); } }
ngOnInit() { this.myForm = this.fb.group({ name: ['', Validators.required], email: ['', [Validators.required, Validators.email]], message: ['', [Validators.required, Validators.minLength(10)]], }); }
<form [formGroup]="myForm" (ngSubmit)="onSubmit(myForm)"> <div> <label> Name: <input formControlName="name" placeholder="Your name"> </label> <div *ngIf="myForm.get('name').invalid && (myForm.get('name').dirty || myForm.get('name').touched)"> Please provide a name. </div> </div> <div> <label> Email: <input formControlName="email" placeholder="Your email"> </label> <div *ngIf="myForm.get('email').invalid && (myForm.get('email').dirty || myForm.get('email').touched)"> Please provide a valid email address. </div> </div> <div> <label> Message: <input formControlName="message" placeholder="Your message"> </label> <div *ngIf="myForm.get('message').invalid && (myForm.get('message').dirty || myForm.get('message').touched)"> Messages must be at least 10 characters long. </div> </div> <button type="submit" [disabled]="myForm.invalid">Send</button> </form>
This code checks to see if the user has interacted with the field (dirty or touched). Then, if the value is not passing the validation requirements, it will display the error message.
The FormArray is a way to manage the collection of Form Controls in Angular. The controls can be a FormGroup, FormControl, or FormArray.
So the idea about formarrray is just like simple array [] and formgroup is just like object {}, that we are using in programing. so inside array we would be element as well as multiple object.
let userTestStatus: { id: number, name: string }= { "id": 0, "name":'Zeeshan' "Available":true };
//Example 1 let userTestStatus:[] = ["id","name", "Available" ]; //Example 2 let userTestStatus={ information: [ { "id": 0, "name":'Zeeshan', "Available":true }, { "id": 1, "name":'Ahsan' "Ready":false }, { "id": 2, "name":'Rehan' "Started":true } ]};
//Example 1 userTestStatusForm=new FormArray(["id", "name", "Available"]) //Example 2 userTestStatusForm=new formGroup({ information=new FormArray([ new FormGroup({ id=new FormControl(0) name=new FormControl('Zeeshan') Available=new FormControl(true) }), new FormGroup({ id=new FormControl(1) name=new FormControl('Ahsan') Available=new FormControl(false) }), new FormGroup({ id=new FormControl(2) name=new FormControl('Rehan') Available=new FormControl(true) }) }) ])
Next, a getter method userInfo, which returns the userInfo FormArray from the userTestStatusForm
get userInfo() : FormArray { return this.userTestStatusForm.get("information") as FormArray }
Adding Some thing in FormArray
Now, we need to add a new info to the information FormArray. Since it is an array we can use the push method to add the new info using the the newInfo method. Note that newInfo() method returns a FormGroup. The name of the FormGroup is its Index in the FormArray.
newInfo(): FormGroup { return new FormGroup({ id=new FormControl(2) name=new FormControl('Rehan') Available=new FormControl(true) }) } addInfo() { this.userInfo.push(this.newInfo()); }
Dynamically Removing Information
Use the removeAt method to remove the element from the skills FromArray.
removeInfo(i:number) { this.userInfo.removeAt(i); }
Template
Skills: <div formArrayName="userInfo"> <div *ngFor="let info of userInfo().controls; let i=index"> <div [formGroupName]="i"> {{i}} id : <input type="text" formControlName="id"> name: <input type="text" formControlName="name"> Available: <input type="text" formControlName="Available"> <button (click)="removeInfo(i)">Remove</button> </div> </div> </div> import { Component, ViewChild, ElementRef } from '@angular/core'; import { FormGroup, FormControl,FormArray, FormBuilder } from '@angular/forms' @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'FormArray Example in Angular Reactive forms'; skillsForm: FormGroup; constructor(private fb:FormBuilder) { userTestStatusForm=new formGroup({ information=new FormArray([ new FormGroup({ id=new FormControl(0) name=new FormControl('Zeeshan') Available=new FormControl(true) }) ]) }) get userInfo() : FormArray { return this.userTestStatusForm.get("information") as FormArray } newInfo(): FormGroup { return new FormGroup({ id=new FormControl(2) name=new FormControl('Rehan') Available=new FormControl(true) }) } addInfo() { this.userInfo.push(this.newInfo()); } removeInfo(i:number) { this.userInfo.removeAt(i); } }