what & when β
βοΈ
how to measure
challengesπ©
π
Local π
zoneless
π
Principal Application Devloper @AON
@pankajparkar
Data / Model / State
Template
DOM
{
"user": {
"firstName": "Pankaj",
"lastName": "Parkar",
"age": 27
}
}
<div class="card">
First Name: {{user.firstName}}
Last Name: {{user.lastName}}
Age: {{user.age}}
</div>
First Name: Pankaj
Last Name: Parkar
Age: 27
28
28
@pankajparkar
In simple word, it synchronises the model changes to view.
export class AppComponent {
title = 'Angular'
}
<span>
{{title}}
</span>
<button (click)="title='Changed'">
Change Title
</button>
Change Title
Angular
Changed
Click
@pankajparkar
ZoneJS
(Default CD)
value = 'No value';
response: any;
http = inject(HttpClient);
// Make API call
networkCall() {
this.http
.get(
'https://jsonplaceholder.typicode.com/todos/1')
.subscribe(
(response: any) => (this.response = response));
}
// work on task
task() {
setTimeout(() => {
this.value = 'Test';
}, 2000);
}
// on button click
startEvent() {
this.networkCall();
this.task();
}
Task - {{value}}
<hr>
Response - {{ response | json }}
<hr>
<button (click)="startEvent()">
Start Event
</button>
ChangeDetectionStrategy.Default
1
2
3
App
Child 1
Child 2
Parent
Grand Child
ππ»
ChangeDetectionStrategy.Default
constructor(appRef: ApplicationRef) {
const originalTick = appRef.tick;
appRef.tick = () => {
originalTick.apply(appRef);
console.log(`App Level CD - ${++this.cdCount}`);
};
}
get test() {
console.log('Update Parent');
return 'Test';
}
ngAfterViewChecked() {
this.count++;
}
value = 'No value';
// Make API call
networkCall() {
this.http
.get('https://xyz.com/todos/1')
.subscribe(
response => this.response = response);
}
// work on task
task() {
setTimeout(() => {
this.value = 'Test';
}, 2000);
}
// on button click
startEvent() {
this.networkCall();
this.task();
}
Task - {{value}}
Response - {{ response | json }}
<hr>
<button (click)="startEvent()">
Start Event
</button>
ChangeDetectionStrategy.OnPush
@Component({...})
export class ParentComponent {
count = 0;
child1Data = { value: 10 };
child2Message = 'Hello from Parent';
cd = inject(ChangeDetectorRef);
ngOnInit() {
setInterval(() => {
this.child1Data = { value: Math.random() };
this.cd.detectChanges();
}, 2000);
setInterval(() => {
this.child2Message = 'Child 2 Message Changed';
this.cd.detectChanges();
}, 4000);
}
ngDoCheck() { this.count++; }
}
<h2>Parent Component CD Counts: {{ count }}</h3>
<app-child1 [data]="child1Data" />
<app-child2 [message]="child2Message" />
<h3>Child Component 1</h3>
<h3>CD Counts: {{ count }}</h3>
<p>Data Value: {{ data?.value }}</p>
<h3>Child Component 2</h3>
<h3>CD Counts: {{ count }}</h3>
<p>Message: {{ message }}</p>
<app-grand-child />
<h3>CD Counts: {{ count }}</h3>
<p>Grand child</p>
App
Child 1
Child 2
Parent
Grand Child
ππ»
ChangeDetectionStrategy.OnPush
OnPush
Skipped
Ran CD
ππ» Click Event Child Comp (tick)
π
π
π
π
π
π
π
π
Property Binding Change
App
Child 1
Child 2
Parent
Grand Child
ChangeDetectionStrategy.OnPush
async pipe (markForCheck)
π
π
π
π
π
π
π
π
Mark for check
OnPush
Skipped
Ran CD
π
π
Property Binding Change
@Component({...})
export class SignalGrandChildComponent {
count = 0;
newSignal = signal(0);
_lastValue = 0;
ngAfterViewChecked() {
this.count++;
}
ngOnInit() {
setInterval(() => {
++this._lastValue;
if (this._lastValue % 3 === 0) {
return;
}
this.newSignal.set(this._lastValue);
}, 1000);
}
}
<h3>CD Counts: {{ count }}</h3>
<p>Grand child</p>
newSignal {{ newSignal() }}
App
Child 1
Child 2
Parent
Grand Child
ChangeDetectionStrategy.OnPush
signal change (markForCheck)
π
π
π
π
π
π
π
π
Skip for refresh
Refresh view
OnPush
Skipped
Ran CD
π
π
Property Binding Change
@Component({...})
export class SignalGrandChildComponent {
count = 0;
newSignal = signal(0);
_lastValue = 0;
ngAfterViewChecked() {
this.count++;
}
ngOnInit() {
setInterval(() => {
++this._lastValue;
if (this._lastValue % 3 !== 0) {
return;
}
this.newSignal.set(this._lastValue);
}, 1000);
}
}
<h3>CD Counts: {{ count }}</h3>
<p>Grand child</p>
newSignal {{ newSignal() }}
- 15kb
Local Change Detection
βOnPush + Signal change
Zoneless change detection
removal on zonejs
under the hood uses scheduler API
βFuture Signal Components