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 how to update values in the form group and use FormBuilder
.
Patching the Model Value
There’re 2 ways to update the model value of Reactive forms.
We can either call setValue
on an individual control to update the value or call patchValue
on a FormGroup
to replace values in the form model.
We can call setValue
as follows:
app.component.ts
:
import { Component } from "@angular/core";
import { FormControl, FormGroup } from "@angular/forms";
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
personForm = new FormGroup({
name: new FormControl(""),
address: new FormGroup({
street: new FormControl("")
})
});
updateName() {
this.personForm.setValue({ ...this.personForm.value, name: "Jane" });
}
}
app.component.html
:
<form [formGroup]="personForm">
<input type="text" formControlName="name" placeholder="Name" />
<div formGroupName="address">
<input type="text" formControlName="street" placeholder="Street" />
</div>
</form><button (click)="updateName()">Update Name</button>
setValue
strictly adheres to the structure of the form group, so we have to include everything as we did in the updateName
method.
If we only want to update some values, we can use the patchValue
method as follows:
app.component.ts
:
import { Component } from "@angular/core";
import { FormControl, FormGroup } from "@angular/forms";
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
personForm = new FormGroup({
name: new FormControl(""),
address: new FormGroup({
street: new FormControl("")
})
});
updateName() {
this.personForm.patchValue({ name: "Jane" });
}
}
app.component.html
:
<form [formGroup]="personForm">
<input type="text" formControlName="name" placeholder="Name" />
<div formGroupName="address">
<input type="text" formControlName="street" placeholder="Street" />
</div>
</form><button (click)="updateName()">Update Name</button>
In the code above, the updateName
method changed to:
this.personForm.patchValue({ name: "Jane" });
As we can see, we don’t have to include all the fields. We only included the ones we want to update.
Generating Form Controls with FormBuilder
We can use the FormBuilder
class to make creating Reactive forms easier for us.
To create a form with FormBuilder
, we can write the following:
app.component.ts
:
import { Component } from "@angular/core";
import { FormBuilder } from "@angular/forms";
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
constructor(private fb: FormBuilder) {}
personForm = this.fb.group({
name: [""],
address: this.fb.group({
street: [""]
})
});
}
app.component.html
:
<form [formGroup]="personForm">
<input type="text" formControlName="name" placeholder="Name" />
<div formGroupName="address">
<input type="text" formControlName="street" placeholder="Street" />
</div>
</form>
The code above has the same functionality as the other examples.
We have a personForm
with the name
field in the root form group and the street
field nested in the address
form group.
Simple Form Validation
To make sure what’s inputted if complete and correct, we have to add form validation to our form.
With Reactive forms, we can ads a single validator to our form control and also display the overall form status.
We can add validation as follows:
app.component.ts
:
import { Component } from "@angular/core";
import { FormBuilder, Validators } from "@angular/forms";
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
constructor(private fb: FormBuilder) {}
personForm = this.fb.group({
name: ["", Validators.required],
address: this.fb.group({
street: ["", Validators.required]
})
});
}
app.component.html
:
<form [formGroup]="personForm">
<input type="text" formControlName="name" placeholder="Name" required />
<div formGroupName="address">
<input type="text" formControlName="street" placeholder="Street" required />
</div>
</form>
In the code above, we made the name
and street
fields required by importing the Validator
and using the required
property in each field.
Also, we have to add the required
attribute in the inputs to prevent errors when the expression has changed after the template has been checked.
Displaying Form Status
We can reference the status
property of our form to get the validator status of our form.
To do this, we just change app.component.html
to the following:
<form [formGroup]="personForm">
<p>Form Status: {{ personForm.status }}</p>
<input type="text" formControlName="name" placeholder="Name" required />
<div formGroupName="address">
<input type="text" formControlName="street" placeholder="Street" required />
</div>
</form>
Now the form should show the validation status of it. personForm.status
returns 'INVALID'
if it’s not valid and 'VALID'
if it’s valid.
Therefore, we should see that in the first line of the form.
Dynamic Controls Using Form Arrays
To add dynamic controls, we can use the FormArray
class.
We can use FormArray
as follows:
app.component.ts
:
import { Component } from "@angular/core";
import { FormBuilder, FormArray } from "@angular/forms";
@Componen({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
constructor(private fb: FormBuilder) {}
personForm = this.fb.group({
names: this.fb.array([this.fb.control("")])
});
get names() {
return this.personForm.get("names") as FormArray;
}
addName() {
this.names.push(this.fb.control(""));
}
}
app.component.html
:
<form [formGroup]="personForm">
<div formArrayName="names">
<h3>Names</h3>
<button (click)="addName()">Add Name</button>
<div *ngFor="let n of names.controls; let i=index">
<label>
Name:
<input type="text" [formControlName]="i" />
</label>
</div>
</div>
</form>
In the code above, we created the names
form array in personForm
.
Then in the template, we loop through the controls with the *ngFor
in the form.
The formControlName
is set to the index of the form control.
We also added an Add Name button to add a new form control.
Conclusion
We can use the FormBuilder
class to save us time when we want to build forms.
It’s also useful for building dynamic forms since it takes FormArrays
.
We can get the status of a form with the status
property of the form group.
To update the values of the form, we can call the setValue
or patchValue
method of a form group.