I've noticed a strange behavior of change detection in Angular. When Observable updated as in the example, change detection not triggered for some reason.
The key here is setTimeout called inside the callback, if you remove it, change detection will work fine. markForCheck which inside AsyncPipe also called as it should.
@Component({
selector: 'my-app',
template:
'<button (click)="click()">Trigger</button> <br> {{value$ | async}}',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AppComponent {
readonly value$ = new BehaviorSubject(1);
constructor(
private readonly zone: NgZone,
) {}
click() {
this.zone.runOutsideAngular(() => {
setTimeout(() => {
this.value$.next(this.value$.value + 1);
console.log(`Change (Should be ${this.value$.value})`);
});
});
}
}
runOutsideOfAngular... there is no change detection in there, is outside ofzone.js... after you do whatever logic in there, in order to add it to the zone, you need to addthis.zone.run()runOutsideAngularif you need change detection in there.. for that, just do your logic withoutNgZone?runOutsideAngular(I don't know why) and potentially puts some observable mutation at the end of the event loop. As a result, this leads to the behavior that I described in the example.