Ionic v9 - Angular - zone.js vs zoneless change detection

I upgraded my app to Angular v22…and I added:

provideZoneChangeDetection()

everything is fine…yesterday I upgraded my app to Ionic v9 …and I saw that this line is added to my components’ ts file:

changeDetection: ChangeDetectionStrategy.Eager

Also in the Ionic Framework documentation of Zoneless change detection..it is mentioned:

When you update component state from an asynchronous callback that Angular did not wrap, nothing schedules a re-render.

Can someone please explain to me in simple terms what is the use of “ChangeDetectionStrategy.Eager” and what is meant by “callback that Angular did not wrap” ?

I am planning to upgrade my app to zoneless change detection.

thank you

Short version: the Eager line came from the Angular v22 migration, not from Ionic. And the “callback Angular did not wrap” bit is about Zone.js no longer being there to tell Angular that something happened.

ChangeDetectionStrategy.Eager Eager is just the old Default under a new name.
It was added in Angular v21.2 with exactly the same behavior as Default, like an alias, and in v22 OnPush finally became the default strategy.

When you run ng update, the v22 migration adds an explicit ChangeDetectionStrategy.Eager to existing components that relied on the old implicit default, so they keep behaving as before.

What the two modes mean in plain terms:

  • Eager: whenever Angular runs a change-detection pass anywhere, this component gets re-checked, no questions asked.
  • OnPush: the component is only checked when Angular has been told it might be dirty, an input changed through a template binding, the component is explicitly marked via ChangeDetectorRef.markForCheck or something that wraps it like the async pipe, an event handler in that component runs, or a signal read in its template changed.

Practically, every Eager in your codebase is now a to-do item: it marks a component that isn’t OnPush-ready yet.

With Zone.js, Angular patches the browser’s async APIs, setTimeout, promises, addEventListener, XMLHttpRequest/fetch. Your callback runs inside the patched version, Zone.js tells Angular “something async just finished”, and Angular runs change detection. That’s why this.items = data in a subscribe() has always just worked. Zoneless removes that. Angular now only learns about changes from a fixed, explicit set of sources. Template event bindings like (click) and (ionChange), host listeners (including the ones Ionic’s value accessors use, so ngModel and reactive forms stay in sync), signal updates read in a template, the async pipe, Ionic page lifecycle hooks that set state synchronously, and navigation/route transitions.

Anything outside that list is “a callback Angular did not wrap”: a raw setTimeout, a resolved await, an RxJS subscribe, a Capacitor plugin listener, a WebSocket onmessage, a third-party SDK callback. The code runs, the field is updated, the view just never repaints. The Ionic docs give the typical examples: state updated after await modal.onWillDismiss() or inside a setTimeout() may need a signal or markForCheck()