Zoneless change detection and Signal in Angular

Bittu Kumar
2 min readOct 5, 2024

--

What is change detection in Angular ?
In Angular, change detection is the mechanism responsible for updating the view when the application’s state changes (data change). The process of syncing HTML view with data is change detection.

It checks for changes in the data model and automatically updates the DOM accordingly.

We will see three small examples showcasing the evolution of change detection in Angular.

Default Change Detection with zone.js:

  • This is the traditional approach where zone.js automatically detects changes
  • Any change to the component’s properties triggers change detection
  • Simple to use but can lead to performance issues large application
// html

<div>
<h3>Counter: {{ counter }}</h3>
<button (click)="startTimer()">Start Timer</button>
</div>


// ts file
counter = 0;

startTimer() {
this.counter = 0;
const source = interval(1000);
source.pipe(take(10)).subscribe(val => {
this.counter = val + 1;
// No need for manual change detection
});
}

OnPush Change Detection:

  • Introduced to improve performance by reducing the number of change detection cycles.
  • Requires manual triggering of change detection: using markForCheck()
// html file
<div>
<h3>Counter: {{ counter }}</h3>
<button (click)="startTimer()">Start Timer</button>
</div>

// ts file
@Component({
selector: 'app-onpush-timer',
changeDetection: ChangeDetectionStrategy.OnPush
})

counter = 0;

constructor(private cd: ChangeDetectorRef) {}

startTimer() {
this.counter = 0;
const source = interval(1000);
source.pipe(take(10)).subscribe(val => {
this.counter = val + 1;
this.cd.markForCheck(); // Manually trigger change detection
});
}

Signal based approach:

  • Uses the signal() function to create reactive properties.
  • The newest method, part of Angular’s move away from zone.js.
  • Changes to signals automatically trigger updates only where needed
  • More explicit and efficient, as it doesn’t rely on zone.js for change detection.
//html
<div>
<h3>Counter: {{ counter() }}</h3>
<button (click)="startTimer()">Start Timer</button>
</div>

// ts file
counter = signal(0);

startTimer() {
this.counter.set(0);
const source = interval(1000);
source.pipe(take(10)).subscribe(val => {
this.counter.set(val + 1);
// No need for manual change detection
});
}

Summary to remember:

  • The default approach relies entirely on zone.js.
  • OnPush requires more manual control but improves performance.
  • Signals provide fine-grained reactivity without zone.js, offering the best performance and developer control.

Thanks for reading. I hope you learnt something today, Reach me out here for more discussion related to angular.

www.linkedin.com/in/bittukumar-web

--

--

Bittu Kumar
Bittu Kumar

Written by Bittu Kumar

Exploring Angular and Frontend development.

No responses yet