SetValue And PatchValue In Angular
In this article, we will learn about the how to set model values in Reactive Forms. The AngularFormsModule's setValue and patchValue functions are used to accomplish this. We'll learn more about setValue and patchValue in this post, as well as the differences between them. With an example, we also learn about the onlySelf and emitEvent parameters.
Angular Forms
There are two ways to create forms with Angular. The first employs a template-driven technique, whereas the second employs a reactive forms approach. In our previous article, we went through both of these topics.
FormControl, FormGroup, and FormArray are the three fundamental building pieces of Angular Forms. All of these components have setValue and patchValue methods, and they all operate differently.
SetValue
Syntax of SetValue
setValue(value: { [key: string]: any; }, options: { onlySelf?: boolean; emitEvent?: boolean; } = {}): void
PatchValue
Syntax of PatchValue
patchValue(value: { [key: string]: any; }, options: { onlySelf?: boolean; emitEvent?: boolean; } = {}): void
onlySelf
When the value of the form changes, Angular examines the form's validation status. The validation process starts with the control whose value was updated and works its way up to the FormGroup top level. This is how things work by default.emitEvent
SetValue Vs PatchValue
Example
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { TemplateComponent } from './template-component'; import { ReactiveComponent } from './reactive.component'; @NgModule({ declarations: [ AppComponent,TemplateComponent,ReactiveComponent ], imports: [ BrowserModule, AppRoutingModule, FormsModule, ReactiveFormsModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
import { Component} from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { }
Now, open the app.component.html file and add the following code
<h1>Angular Forms SetValue & PatchValue Example</h1> <ul> <li> <a [routerLink]="['/template']" routerLinkActive="router-link-active" >Template</a> </li> <li> <a [routerLink]="['/reactive']" routerLinkActive="router-link-active" >Reactive</a> </li> </ul> <router-outlet></router-outlet>
SetValue & PatchValue in Reactive Forms
import { Component, OnInit } from '@angular/core'; import { FormGroup, FormControl, Validators } from '@angular/forms' @Component({ templateUrl: './reactive.component.html', }) export class ReactiveComponent implements OnInit { title = 'Reactive Forms'; countryList: country[] = [ new country("1", "India"), new country('2', 'USA'), new country('3', 'England') ]; // reactiveForm = new FormGroup({ // firstname: new FormControl('Sachin'), // lastname: new FormControl('Tendulkar'), // email: new FormControl('sachin@gmail.com'), // gender: new FormControl('male'), // isMarried: new FormControl(true), // country: new FormControl('2'), // address:new FormGroup({ // city: new FormControl("Mumbai"), // street: new FormControl("Perry Cross Rd"), // pincode:new FormControl("400050") // }) // }) reactiveForm = new FormGroup({ firstname: new FormControl(), lastname: new FormControl(), email: new FormControl(), gender: new FormControl(), isMarried: new FormControl(), country: new FormControl(), address:new FormGroup({ city: new FormControl(), street: new FormControl(), pincode:new FormControl() }) }) onSubmit() { console.log(this.reactiveForm.value); } ngOnInit() { this.setDefault(); } setDefault() { let contact = { firstname: "Sachin", lastname: "Tendulkar", email: "sachin@gmail.com", gender: "male", isMarried: true, country: "2", address: { city: "Mumbai", street: "Perry Cross Rd", pincode: "400050" } }; this.reactiveForm.setValue(contact); } setValue() { let contact = { firstname: "Rahul", lastname: "Dravid", email: "rahul@gmail.com", gender: "male", isMarried: true, country: "1", address: { city: "Bangalore", street: "Brigade Road", pincode: "600070" } }; this.reactiveForm.setValue(contact); } setAddress() { let address= { city: "Bangalore", street: "Brigade Road", pincode: "600070", }; this.reactiveForm.get("address").setValue(address); }; setCountry() { this.reactiveForm.get("country").setValue("1"); }; patchAddress() { let address= { city: "Bangalore", street: "Brigade Road", //pincode: "600070", //firstname:'saurv' }; this.reactiveForm.get("address").patchValue(address); } patchName() { let contact = { firstname: "Rahul", lastname: "Dravid", } this.reactiveForm.patchValue(contact); } reset() { this.reactiveForm.reset(); } } export class country { id: string; name: string; constructor(id: string, name: string) { this.id = id; this.name = name; } }
Now, open the reactive-component.html file and add the following code.
<h3>{{title}}</h3> <div style="float: left; width:50%;"> <form [formGroup]="reactiveForm" (ngSubmit)="onSubmit()" novalidate> <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="isMarried">Married </label> <input type="checkbox" id="isMarried" name="isMarried" formControlName="isMarried"> </p> <p> <label for="country">country </label> <select id="country" name="country" formControlName="country"> <option [ngValue]="c.id" *ngFor="let c of countryList"> {{c.name}} </option> </select> </p> <div formGroupName="address"> <p> <label for="city">City</label> <input type="text" class="form-control" name="city" formControlName="city"> </p> <p> <label for="street">Street</label> <input type="text" class="form-control" name="street" formControlName="street"> </p> <p> <label for="pincode">Pin Code</label> <input type="text" class="form-control" name="pincode" formControlName="pincode"> </p> </div> <button>Submit</button> <div> <button type="button" (click)="setDefault()">Default</button> </div> <div> <button type="button" (click)="setValue()">SetValue</button> <button type="button" (click)="setAddress()">Address</button> <button type="button" (click)="setCountry()">Country</button> </div> <div> <button type="button" (click)="patchName()">Name</button> <button type="button" (click)="patchAddress()">Address</button> <button type="button" (click)="reset()">Reset</button> </div> </form> </div> <div style="float: right; width:50%;"> <h3>Form Status</h3> <b>valid : </b>{{reactiveForm.valid}} <b>invalid : </b>{{reactiveForm.invalid}} <b>touched : </b>{{reactiveForm.touched}} <b>untouched : </b>{{reactiveForm.untouched}} <b>pristine : </b>{{reactiveForm.pristine}} <b>dirty : </b>{{reactiveForm.dirty}} <b>disabled : </b>{{reactiveForm.disabled}} <b>enabled : </b>{{reactiveForm.enabled}} <h3>Form Value</h3> {{reactiveForm.value |json}} </div>
Setting Initial /Default Value
reactiveForm = new FormGroup({ firstname: new FormControl('Sachin'), lastname: new FormControl('Tendulkar'), email: new FormControl('sachin@gmail.com'), gender: new FormControl('male'), isMarried: new FormControl(true), country: new FormControl('2'), address:new FormGroup({ city: new FormControl("Mumbai"), street: new FormControl("Perry Cross Rd"), pincode:new FormControl("400050") }) })
Another alternative is to use the ngOnInit method's setValue method. To do so, build a contact object with properties that match the Form Model perfectly, and then use the setValue method as shown below.
ngOnInit() { this.setDefault(); } setDefault() { let contact = { firstname: "Sachin", lastname: "Tendulkar", email: "sachin@gmail.com", gender: "male", isMarried: true, country: "2", address: { city: "Mumbai", street: "Perry Cross Rd", pincode: "400050" } }; this.reactiveForm.setValue(contact); }
Must supply a value for form control with name: 'isMarried'.
Cannot find form control with name: surname.
Nested FormGroup
setAddress() { let address= { city: "Bangalore", street: "Brigade Road", pincode: "600070", }; this.reactiveForm.get("address").setValue(address); };
FormControl
setCountry() { this.reactiveForm.get("country").setValue("1"); };
PatchValue
patchAddress() { let address= { city: "Bangalore", street: "Brigade Road", }; this.reactiveForm.get("address").patchValue(address); } patchName() { let contact = { firstname: "Rahul", lastname: "Dravid", }
this.reactiveForm.patchValue(contact);
Reset Form
reset() { this.reactiveForm.reset(); }
OnlySelf Example
withOutOnlySelf(){ this.reactiveForm.get("firstname").setValue(""); }
Fill in the firstname field with text to make the form valid again. Try it again, but this time with onlySelf:true. The form continues to be valid.
withOnlySelf(){ this.reactiveForm.get("firstname").setValue("",{onlySelf:true}); }
emitEvent example
ngOnInit() { this.setDefault(); this.reactiveForm.get("firstname").statusChanges.subscribe(x => { console.log('firstname status changes') }) this.reactiveForm.get("firstname").valueChanges.subscribe(x => { console.log('firstname value changed') }) this.reactiveForm.statusChanges.subscribe(x => { console.log('form status changes') }) this.reactiveForm.valueChanges.subscribe(x => { console.log('form value changed') }) }
Then update the value of the firstname, and all four events will be triggered.
withouEmitEvent(){ this.reactiveForm.get("firstname").setValue("Sachin"); }
The events are muted when emitEvent:false is used.
withEmitEvent(){ this.reactiveForm.get("firstname").setValue("",{emitEvent:false}); }
SetValue & PatchValue in Template-driven Forms
@ViewChild('templateForm',null) templateForm: NgForm;
Once we have the reference, we can use SetValue and PatchValue, as illustrated in the examples below. Refer to the Angular article Set Value in Template-Driven Forms for a more complete explanation.
Open the template-component.ts file and put the following code
import { Component, ViewChild, ElementRef, OnInit } from '@angular/core'; import { NgForm } from '@angular/forms'; @Component({ templateUrl: './template.component.html', }) export class TemplateComponent implements OnInit { title = 'Template driven forms'; @ViewChild('templateForm',null) templateForm: NgForm; countryList: country[] = [ new country("1", "India"), new country('2', 'USA'), new country('3', 'England') ]; contact: contact; onSubmit() { console.log(this.templateForm.value); } ngOnInit() { setTimeout(() => { this.setDefault(); }); } setDefault() { let contact = { firstname: "Sachin", lastname: "Tendulkar", email: "sachin@gmail.com", gender: "male", isMarried: true, country: "2", address: { city: "Mumbai", street: "Perry Cross Rd", pincode: "400050" } }; this.templateForm.control.setValue(contact); } setValue() { let contact = { firstname: "Rahul", lastname: "Dravid", email: "rahul@gmail.com", gender: "male", isMarried: true, country: "1", address: { city: "Bangalore", street: "Brigade Road", pincode: "600070" } }; this.templateForm.setValue(contact); } setAddress() { let address= { city: "Bangalore", street: "Brigade Road", pincode: "600070" }; this.templateForm.control.get("address").setValue(address); }; setCountry() { let address= { city: "Bangalore", street: "Brigade Road", pincode: "600070" }; this.templateForm.control.get("country").setValue("1"); }; patchAddress() { let address= { city: "Bangalore", street: "Brigade Road", //pincode: "600070", //firstname:'saurv' }; this.templateForm.control.get("address").patchValue(address); } patchName() { let contact = { firstname: "Rahul", lastname: "Dravid", } this.templateForm.control.patchValue(contact); } reset() { this.templateForm.reset(); } } export class contact { firstname:string; lastname:string; gender:string; email:string; isMarried:boolean; country:string; address: { city:string; street:string; pincode:string; } } export class country { id: string; name: string; constructor(id: string, name: string) { this.id = id; this.name = name; } }
Now, open the template-component.html file and the following code
<h3>{{title}}</h3> <div style="float: left; width:50%;"> <form #templateForm="ngForm" (ngSubmit)="onSubmit(templateForm)"> <p> <label for="firstname">First Name </label> <input type="text" id="firstname" name="firstname" #fname="ngModel" ngModel> </p> <p> <label for="lastname">Last Name </label> <input type="text" id="lastname" name="lastname" ngModel> </p> <p> <label for="email">Email </label> <input type="text" id="email" name="email" ngModel> </p> <p> <label for="gender">Geneder </label> <input type="radio" value="male" id="gender" name="gender" ngModel> Male <input type="radio" value="female" id="gender" name="gender" ngModel> Female </p> <p> <label for="isMarried">Married </label> <input type="checkbox" id="isMarried" name="isMarried" ngModel> </p> <p> <label for="country">country </label> <select id="country" name="country" ngModel> <option [ngValue]="c.id" *ngFor="let c of countryList"> {{c.name}} </option> </select> </p> <div ngModelGroup="address"> <p> <label for="city">City</label> <input type="text" id="city" name="city" ngModel> </p> <p> <label for="street">Street</label> <input type="text" id="street" name="street" ngModel> </p> <p> <label for="pincode">Pin Code</label> <input type="text" id="pincode" name="pincode" ngModel> </p> </div> <p> <button type="submit">Submit</button> </p> <div> <button type="button" (click)="setDefault()">Default</button> </div> <div> <button type="button" (click)="setValue()">SetValue</button> <button type="button" (click)="setAddress()">Address</button> <button type="button" (click)="setCountry()">Country</button> </div> <div> <button type="button" (click)="patchName()">Name</button> <button type="button" (click)="patchAddress()">Address</button> <button type="button" (click)="reset()">Reset</button> </div> </form> </div> <div style="float: right; width:50%;"> <h3>Form Status</h3> <b>valid : </b>{{templateForm.valid}} <b>invalid : </b>{{templateForm.invalid}} <b>touched : </b>{{templateForm.touched}} <b>untouched : </b>{{templateForm.untouched}} <b>pristine : </b>{{templateForm.pristine}} <b>dirty : </b>{{templateForm.dirty}} <b>disabled : </b>{{templateForm.disabled}} <b>enabled : </b>{{templateForm.enabled}} <h3>Form Value</h3> {{templateForm.value | json }} </div>