Fine-grained control over Angular's change detection is now available and practical to use.
While signals-based change detection optimization is not fully mature yet, there are already effective strategies for managing change detection efficiently.
The reactive extensions for Angular, RxAngular, ship with a suite of tools designed to help you control and tune application performance. Among them is the unpatch directive.
Understanding the Unpatch Directive
Angular's NgZone service governs where tasks run in relation to the change detection system. Experienced Angular developers often refer to this as working within two zones. By default, Angular executes nearly everything inside an Angular zone, which means that asynchronous operations such as setTimeout, promises, and all DOM events automatically kick off change detection.
This built-in behavior keeps the UI synchronized with the latest data, but it can become a bottleneck when dealing with high-frequency events like mousemove or scroll. Such events can lead to a flood of redundant change detection cycles.
The unpatch directive addresses this problem directly. By applying it, you can stop certain events from causing change detection to run, thereby enhancing performance. The directive works on any element that has event bindings.
<button unpatch (click)="triggerSomeMethod($event)">click me</button>
Here, the unpatch directive stops the 'click' event from initiating change detection. By default, it unpatch all registered listeners on its host element. If you need more precision, you can pass a list of events to exclude, as demonstrated below.
Putting unpatch to Work in Your Application
Consider a practical use case where unpatch can make a noticeable difference. Picture a real-time data visualization dashboard that manages a substantial number of DOM nodes and reacts to frequent events such as mousemove and scroll.
Initially, we have a component that renders a large dataset in a table. Each row includes a hover effect that reveals extra details.
<div *ngFor="let data of largeDataSet">
<div (mousemove)="showAdditionalData(data)" class="data-row">
<!-- Basic data display -->
</div>
</div>
In this situation, the mousemove event fires at a high rate, forcing change detection across the entire component tree. Even when the additional data stays the same, Angular will still re-render the tree, which hurts performance.
Let's see how unpatch improves this:
<div *ngFor="let data of largeDataSet">
<div [unpatch]="['mousemove']" (mousemove)="showAdditionalData(data)" class="data-row">
<!-- Basic data display -->
</div>
</div>
With unpatch, we tell Angular to skip change detection whenever 'mousemove' is triggered.
Kanban Board
Think about a Kanban board application where users move tasks between columns using drag and drop.
<div class="task"
(dragstart)="dragStart($event, task)"
(dragover)="dragOver($event)"
(drop)="drop($event, column)">
<!-- Task display -->
</div>
Here, the dragstart, dragover, and drop events fire while a user drags a task and releases it into another column. Every one of these events triggers change detection, which can cause degradation, especially as the number of tasks grows.
Now, we apply unpatch for optimization:
<div class="task"
[unpatch]="['dragstart', 'dragover', 'drop']"
(dragstart)="dragStart($event, task)"
(dragover)="dragOver($event)"
(drop)="drop($event, column)">
<!-- Task display -->
</div>
By incorporating the unpatch directive, the dragstart, dragover, and drop events will no longer force change detection. Consequently, the application's performance can see a marked improvement during frequent drag and drop interactions.
However, be aware that you will need to manually invoke change detection if any of these events modify state that needs to be reflected in the view!
Angular's ChangeDetectorRef service gives you the ability to run change detection manually for a specific component and its children. The detectChanges method allows you to do this explicitly:
constructor(private changeDetector: ChangeDetectorRef) {}
drop(event: DragEvent, column: Column) {
// logic
// manually trigger change detection
this.changeDetector.detectChanges();
}
The unpatch directive from the RxAngular library is a valuable asset for fine-tuning Angular applications. By cutting down on unnecessary change detection runs, it contributes to smoother performance and more responsive user interfaces.
Be sure to explore the other utilities RxAngular has to offer.
Thanks for reading!
If you enjoyed this piece, you might be interested in what I'm doing on Twitter. I host live Twitter Spaces on Angular with GDEs and industry experts. You can join the conversation live, ask your questions, or catch the replays as short clips.
Feel free to follow me on Twitter @DanielGlejzner — it would mean a lot. Thank you!




