From 5b5ea059e9d345e8df584d6fe6ccfb0ef5e15a0b Mon Sep 17 00:00:00 2001 From: ldef <30657261+ldef@users.noreply.github.com> Date: Thu, 13 Nov 2025 10:58:37 +0100 Subject: [PATCH 1/4] doc: Zoneless updates --- docs/general/configuration.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/docs/general/configuration.md b/docs/general/configuration.md index a52dee0..44a88f1 100644 --- a/docs/general/configuration.md +++ b/docs/general/configuration.md @@ -18,6 +18,7 @@ Standalone components are self-contained which is much easier to manage, and rem You can run the [schematic migration](https://angular.dev/reference/migrations/standalone) to automatically convert your project to standalone. ::: +## Zoneless **Consider** using [Zoneless](https://angular.dev/guide/zoneless). :::info Why? @@ -28,6 +29,37 @@ Opting for Zoneless mode is a future-proof choice as Angular is moving towards t When using third-party libraries that depend on `zone.js`, you may need to keep zone-based change detection enabled. Some libraries or tools might not function correctly without it, so evaluate compatibility before switching to Zoneless mode. ::: +**To activated Zoneless feature :** + +```ts title="✅ Activate Zoneless" +// main.ts +bootstrapApplication(AppComponent, { +  providers: [provideZonelessChangeDetection()], +}) +``` + +```ts title="✅ Remove ZoneJs form project" +// angular.json +"polyfills": [ +  // "zone.js",          <-- to remove +  // "zone.js/testing"   <-- to remove +] +``` + +**Do** use [Signals](../reactivity#signals). + +**Do** use [Async Pipe](../reactivity#managing-subscriptions). + +**Do** Clean up legacy code: replace `NgZone usage` (e.g., `run`, `onStable`) with reactive patterns (Signals/effects) or dedicated rendering hooks for post-render scenarios. + +**Do** migrate unit tests on Zoneless mode : + +```ts title="✅ Activate Zoneless in tests" +TestBed.configureTestingModule({ +  providers: [provideZonelessChangeDetection()], +}) +``` + ## Git **Do** commit `package.json` and `package-lock.json` files. From 840913273347bb0abb6f336f41e1d318a91b7883 Mon Sep 17 00:00:00 2001 From: ldef <30657261+ldef@users.noreply.github.com> Date: Fri, 5 Dec 2025 14:36:36 +0100 Subject: [PATCH 2/4] Update configuration.md --- docs/general/configuration.md | 43 ++++++++++++++++------------------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/docs/general/configuration.md b/docs/general/configuration.md index 44a88f1..9fd700e 100644 --- a/docs/general/configuration.md +++ b/docs/general/configuration.md @@ -29,36 +29,33 @@ Opting for Zoneless mode is a future-proof choice as Angular is moving towards t When using third-party libraries that depend on `zone.js`, you may need to keep zone-based change detection enabled. Some libraries or tools might not function correctly without it, so evaluate compatibility before switching to Zoneless mode. ::: -**To activated Zoneless feature :** +**What It Means and How to Adapt** -```ts title="✅ Activate Zoneless" -// main.ts -bootstrapApplication(AppComponent, { -  providers: [provideZonelessChangeDetection()], -}) -``` +Zoneless mode represents a major shift in Angular’s change detection strategy. Historically, Angular relied on Zone.js, a patching library that intercepted asynchronous tasks—timers, promises, events—to automatically trigger UI updates. With zoneless, this implicit mechanism is gone. Angular no longer monitors every async operation; instead, updates happen only when the framework knows something changed. -```ts title="✅ Remove ZoneJs form project" -// angular.json -"polyfills": [ -  // "zone.js",          <-- to remove -  // "zone.js/testing"   <-- to remove -] -``` +**Key Impacts** -**Do** use [Signals](../reactivity#signals). +**Do** Watch for UI not updating after async operations (state changes happen, but rendered HTML does not reflect them). -**Do** use [Async Pipe](../reactivity#managing-subscriptions). +**Do** Check for legacy code using NgZone or relying on implicit refresh after timers, HTTP calls, or event handlers. -**Do** Clean up legacy code: replace `NgZone usage` (e.g., `run`, `onStable`) with reactive patterns (Signals/effects) or dedicated rendering hooks for post-render scenarios. +**Do** Use debugging tools or logs to confirm: if state changes but the DOM stays stale, you need explicit triggers. -**Do** migrate unit tests on Zoneless mode : -```ts title="✅ Activate Zoneless in tests" -TestBed.configureTestingModule({ -  providers: [provideZonelessChangeDetection()], -}) -``` +**How to fix change due to Zoneless** + +**Do** Use [Signals](../reactivity#signals) for local state. Signals integrate with Angular’s rendering engine: reading a signal in a template registers it for updates, and calling set() or update() marks the view dirty automatically. + +**Do** Use [Async Pipe](../reactivity#managing-subscriptions) for Observables. It subscribes and triggers view checks on each emission, replacing the implicit Zone.js refresh. + +**Do** Combine Signals and RxJS when needed. Convert streams to signals with toSignal() for unified template usage while keeping Observables for complex async flows. + +**Do** Trigger updates through Angular events—user interactions, input changes, lifecycle hooks—rather than relying on patched async tasks. + +**Do** Keep OnPush as your default strategy. It aligns with explicit updates and avoids unnecessary checks. + +**Do** For tests, configure TestBed in zoneless mode and use explicit triggers (signal updates, Observable emissions) instead of waiting for microtasks. + ## Git From fc97eefe4dd9e96c1e594a927f53768390207276 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Bou=C3=A9?= Date: Fri, 19 Dec 2025 16:39:04 +0100 Subject: [PATCH 3/4] doc: create change detection page --- docs/component/_category_.yml | 3 +- docs/component/change-detection.md | 63 ++++++++++++++++++++++++++++++ docs/component/reusability.md | 2 +- docs/component/typescript-class.md | 19 --------- docs/general/configuration.md | 38 ------------------ docs/reactivity.md | 8 ++++ 6 files changed, 74 insertions(+), 59 deletions(-) create mode 100644 docs/component/change-detection.md diff --git a/docs/component/_category_.yml b/docs/component/_category_.yml index d997133..b7b0e02 100644 --- a/docs/component/_category_.yml +++ b/docs/component/_category_.yml @@ -1,4 +1,5 @@ label: Component position: 3 link: - type: generated-index \ No newline at end of file + type: generated-index +className: new \ No newline at end of file diff --git a/docs/component/change-detection.md b/docs/component/change-detection.md new file mode 100644 index 0000000..f2fd58a --- /dev/null +++ b/docs/component/change-detection.md @@ -0,0 +1,63 @@ +--- +sidebar_position: 4 +--- +# Change detection + +Change detection is a core concept in Angular that ensures the UI stays in sync with the application state. This guide explores best practices for managing change detection effectively, including strategies for optimizing performance and leveraging Angular's built-in mechanisms. + +## General guidelines + +**Consider** using `ChangeDetectionStrategy.OnPush` for every components. +- ❌ unspecified change detection strategy +- ❌ `changeDetection: ChangeDetectionStrategy.Default` +- ✅ `changeDetection: ChangeDetectionStrategy.OnPush` + +:::info Why? +The main reason is sustainability. Angular is heading towards better reactivity with signals and Zoneless application, and using `OnPush` now will make migration to future major releases easier. + +In addition, `OnPush` strategy improves performances by reducing the number of change detection cycles, which is particularly interesting for large projects. +::: + +:::tip +You can set the default change detection strategy to `OnPush` in your `angular.json` file for components generated with Angular CLI. +::: + +**Do** rely on reactive primitives to trigger change detection. + +- ✅ [Signals](../reactivity#signals) - reading a signal in a template registers it for updates, and calling `set()` or `update()` marks the view dirty. +- ✅ [Async Pipe](../reactivity#managing-subscriptions) - it subscribes to an Observable and triggers view checks on each emission. +- ✅ Event handlers, e.g. `(click)` or `(keydown)`. +- ✅ Input property changes from parent to child components. +- ❌ Timers, e.g. `setTimeout()` or `setInterval()`. +- ❌ HTTP requests + +:::tip +As a last resort, you can use `markForCheck()` method from `ChangeDetectorRef` to manually trigger change detection. +::: + +See [Reactivity](../reactivity.md) for more details. + +## Zoneless + +Zoneless mode represents a major shift in Angular’s change detection strategy. Historically, Angular relied on Zone.js, a patching library that intercepted asynchronous tasks—timers, promises, events—to automatically trigger UI updates. With zoneless, this implicit mechanism is gone. Angular no longer monitors every async operation; instead, updates happen only when the framework knows something changed. + +**Consider** using [Zoneless](https://v21.angular.dev/guide/zoneless). + +:::info Why? +Opting for Zoneless mode is a future-proof choice as Angular is moving towards this direction. While the performance enhancement is minimal (especially if you have already followed best practices, e.g. [`OnPush` change detection](../component/typescript-class#change-detection)), it can improve developer experience by providing clearer stack traces. Additionally, it'll help reduce bundle size and startup time. +::: + +:::tip +To migrate existing code to Zoneless mode, check for legacy code using `NgZone` or relying on implicit change detection after timers, HTTP calls, or event handlers. The most encountered problem is a piece of UI that does not reflect a state change until you interact with it. If state changes but the DOM stays stale, you can use debugging tools or logs to confirmand reactive patterns mentioned above to fix it. +::: + +:::warning Exceptions +When using third-party libraries that depend on `zone.js`, you may need to keep zone-based change detection enabled. Some libraries or tools might not function correctly without it, so evaluate compatibility before switching to Zoneless mode. +::: + +### Testing + +**Do** provide zoneless change detection in tests. +- ✅ `provideZonelessChangeDetection()` in `TestBed.configureTestingModule()` +- ❌ `fixture.detectChanges()` + diff --git a/docs/component/reusability.md b/docs/component/reusability.md index 69d6d96..ea94d8a 100644 --- a/docs/component/reusability.md +++ b/docs/component/reusability.md @@ -1,6 +1,6 @@ --- draft: true -sidebar_position: 4 +sidebar_position: 5 --- # Reusability - seperation of concern (the art of creating reusable components) diff --git a/docs/component/typescript-class.md b/docs/component/typescript-class.md index 81b0fe1..354edae 100644 --- a/docs/component/typescript-class.md +++ b/docs/component/typescript-class.md @@ -94,25 +94,6 @@ You can run [schematic migrations](https://v21.angular.dev/reference/migrations) - ❌ `selected = input(false)` and `selectedChange = output()` - ✅ `selected = model(false)` -## Change detection - -**Consider** using `ChangeDetectionStrategy.OnPush` for every components. -- ❌ unspecified change detection strategy -- ❌ `changeDetection: ChangeDetectionStrategy.Default` -- ✅ `changeDetection: ChangeDetectionStrategy.OnPush` - -:::info Why? -The main reason is sustainability. Angular is heading towards better reactivity with signals and Zoneless application, and using `OnPush` now will make migration to future major releases easier. - -In addition, `OnPush` strategy improves performances by reducing the number of change detection cycles, which is particularly interesting for large projects. -::: - -:::tip -You can set the default change detection strategy to `OnPush` in your `angular.json` file for components generated with Angular CLI. -::: - -More info about change detection in [Reactivity](../reactivity.md). - ## Lifecycle **Avoid** misusing or overusing component lifecycle hooks. diff --git a/docs/general/configuration.md b/docs/general/configuration.md index b9c40a9..3d2564f 100644 --- a/docs/general/configuration.md +++ b/docs/general/configuration.md @@ -18,44 +18,6 @@ Standalone components are self-contained which is much easier to manage, and rem You can run the [schematic migration](https://v21.angular.dev/reference/migrations/standalone) to automatically convert your project to standalone. ::: -**Consider** using [Zoneless](https://v21.angular.dev/guide/zoneless). - -:::info Why? -Opting for Zoneless mode is a future-proof choice as Angular is moving towards this direction. While the performance impact is minimal (especially if you have already followed best practices, e.g. [`OnPush` change detection](../component/typescript-class#change-detection)), it can improve developer experience by providing clearer stack traces. Additionally, it'll help reduce bundle size and startup time. -::: - -:::warning Exceptions -When using third-party libraries that depend on `zone.js`, you may need to keep zone-based change detection enabled. Some libraries or tools might not function correctly without it, so evaluate compatibility before switching to Zoneless mode. -::: - -**What It Means and How to Adapt** - -Zoneless mode represents a major shift in Angular’s change detection strategy. Historically, Angular relied on Zone.js, a patching library that intercepted asynchronous tasks—timers, promises, events—to automatically trigger UI updates. With zoneless, this implicit mechanism is gone. Angular no longer monitors every async operation; instead, updates happen only when the framework knows something changed. - -**Key Impacts** - -**Do** Watch for UI not updating after async operations (state changes happen, but rendered HTML does not reflect them). - -**Do** Check for legacy code using NgZone or relying on implicit refresh after timers, HTTP calls, or event handlers. - -**Do** Use debugging tools or logs to confirm: if state changes but the DOM stays stale, you need explicit triggers. - - -**How to fix change due to Zoneless** - -**Do** Use [Signals](../reactivity#signals) for local state. Signals integrate with Angular’s rendering engine: reading a signal in a template registers it for updates, and calling set() or update() marks the view dirty automatically. - -**Do** Use [Async Pipe](../reactivity#managing-subscriptions) for Observables. It subscribes and triggers view checks on each emission, replacing the implicit Zone.js refresh. - -**Do** Combine Signals and RxJS when needed. Convert streams to signals with toSignal() for unified template usage while keeping Observables for complex async flows. - -**Do** Trigger updates through Angular events—user interactions, input changes, lifecycle hooks—rather than relying on patched async tasks. - -**Do** Keep OnPush as your default strategy. It aligns with explicit updates and avoids unnecessary checks. - -**Do** For tests, configure TestBed in zoneless mode and use explicit triggers (signal updates, Observable emissions) instead of waiting for microtasks. - - ## Git **Do** commit `package.json` and `package-lock.json` files. diff --git a/docs/reactivity.md b/docs/reactivity.md index 5bd6819..86160b6 100644 --- a/docs/reactivity.md +++ b/docs/reactivity.md @@ -153,6 +153,14 @@ Since these new tools will most likely become the future of Angular, and that th **Consider** using [signals](#signals) instead of RxJs `BehaviorSubject`. +### Interoperability with signals + +**Do** use `toSignal()` to convert an Observable to a Signal. + +:::tip +You can combine Signals and RxJS when needed. Convert streams to signals with `toSignal()` for unified template usage while keeping Observables for complex async flows. +::: + ### Managing subscriptions **Do** unsubcribe from observables. From b2f58f436cc44c3ed7db7ebf90cf43d048d7176e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Bou=C3=A9?= Date: Fri, 19 Dec 2025 16:49:46 +0100 Subject: [PATCH 4/4] doc: new sidebar tag zoneless --- docs/component/change-detection.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/component/change-detection.md b/docs/component/change-detection.md index f2fd58a..7657653 100644 --- a/docs/component/change-detection.md +++ b/docs/component/change-detection.md @@ -1,5 +1,6 @@ --- sidebar_position: 4 +sidebar_class_name: new --- # Change detection