In this tutorial, We’ll learn how to use ngZone in angular and demonstrate how to apply them to your Angular applications.
We’ll start by talking about Angular’s Zone concept and why ngZone are important for enhancing the stability and speed of your applications.
Then, we’ll get into some code examples that show how to use ngZone to run code outside the typical change detection process using real-world examples.
Table of Contents
Understanding NgZone in Angular ?
Ever wonder how Angular knows when template bindings need to be updated?
In fact, ngZone handles notifying Angular when to perform the change detection process.
Now let’s see what is actually triggering the change detection cycle to execute in our applications. Or, more specifically, what can change the states in our angular applications
The state is influenced by three factors:
- Events: Browser events like button
click
,input
… - XMLHttpRequests : Fetching Data from the server, call API …
- Timers:
setTimeout()
,setInterval
Using Events to run code inside the angular zone
Now let’s see how to run the code inside the angular Zone using Events (Button click)
import {Component} from "@angular/core";
@Component({
selector: "my-app",
templateUrl: "./app.component.html"
})
export class AppComponent {
onClick(): void {
console.log("onClick");
}
}
When you click the button, the change detection process and the event listener data-bound are both launched.
Now, we will update the onClick()
method and try to run the code outside the angular zone to prevent running the change detection cycle.
import {Component, NgZone } from "@angular/core";
@Component({
selector: "my-app",
templateUrl: "./app.component.html"
})
export class AppComponent {
constructor(private readonly zone: NgZone) {}
onClick() {
this.zone.runOutsideAngular(() => {
console.log("onClick is running outside angular Zone");
});
}
}
The following alternative, which simply runs the callback outside the NgZone
, will never prevent the change detection process from taking place.
It will only disable the button click event.
Using HttpRequest to run code inside the angular zone
Using the Http service to retrieve the data from the server, we will attempt to modify the application state in the example above.
import {Component} from "@angular/core";
@Component({
selector: "my-app",
templateUrl: "./app.component.html"
})
export class AppComponent {
userList: User[];
constructor(private userService: UserService) {}
ngOnInit() {
this.getUserData();
}
getUserData() :void {
this.userService.fetchDataServer()
.subscribe(userListFromServer => {
this.userList = userListFromServer;
// use userList data to bind it to the view
});
}
}
In this example, when we subscribe to the observable, we update the userList
value, and NgZone
notifies Angular to perform the change detection process and apply the modification to the component view.
Now, if we only want to update the userList
value without running the change detection process and thus not updating the userList
in the component View,
We can simply run the code outside the angular zone by calling zone.runOutsideAngular()
import {Component} from "@angular/core";
@Component({
selector: "my-app",
templateUrl: "./app.component.html"
})
export class AppComponent {
userList: User[];
constructor(private userService: UserService, private readonly zone: NgZone) {}
ngOnInit() {
this.zone.runOutsideAngular(() => {
this.getUserData();
// running outside angular Zone
// so the change detection will not be executed
// so the template will not be changed
});
}
getUserData() :void {
this.userService.fetchDataServer()
.subscribe(userListFromServer => {
this.userList = userListFromServer;
});
}
}
How NgZone is working ?
Angular must be always notified that the property has been updated and should perform change detection.
Angular uses a library called zone.js
to solve this problem.
While Zone.js
may observe all stages of synchronous and asynchronous processes, Angular also provides a service named NgZone
.
This service establishes a separated zone to automatically trigger change detection when a sync or async function is executed.
Zones are made up in a hierarchy of parent-child relationships, as you can see in the following schema. Initially, a unique root zone is used by the browser.
NgZone Events
A new job that performs change detection for the entire application is started whenever Angular’s zone emits a onTurnDone
event.
NgZone
typically has three important events that can be emitted : onTurnStart()
, onEventDone()
and onTurnDone()
.
Let’s now examine the code used to notify Angular to perform change detection.
ObservableWrapper.subscribe(this.zone.onTurnDone, () => {
this.zone.run(() => {
this.tick();
});
});
tick() {
this.changeDetectorRefs.forEach((detector) => {
detector.detectChanges();
});
}
If you look at the code, you will notice that the tick(
) method loops over the changeDetectorRefs
object array and running the change detection on each entry.
As you see in the following screenshot, If we console log the changeDetectorRefs
object, we will get all the elements of the application.
So NgZone will notify angular to perform change detection process for the entire application.