Skip to content

RFC: Targeted Reactivity with an @isolated block #70333

Description

@aminesbdev

Feature Request: Targeted Reactivity with an @isolated block

Motivation

With the introduction of Signals and the push towards a Zoneless architecture, Angular's reactivity has become significantly more robust. However, change detection is still somewhat tied to the component tree. As explicitly mentioned in the core codebase (packages/core/src/render3/reactive_lview_consumer.ts), all embedded views currently share a consumer with the component view.

This means that if a signal changes deep within a heavy component, the entire component's template must be re-evaluated. For large data grids, dashboards, or complex forms, this lack of fine-grained DOM updates can lead to performance bottlenecks, forcing developers to artificially split their templates into smaller sub-components just for the sake of performance.

Proposed Solution

I propose introducing an @isolated (or @reactive, @memo) control flow block that grants its embedded view its own independent reactive consumer.

<heavy-dashboard>
  <!-- Lots of static or heavy DOM elements here -->
  
  @isolated {
    <!-- If `clockSignal()` changes, ONLY this embedded view is refreshed.
         The parent <heavy-dashboard> component is completely bypassed. -->
    <div class="clock">{{ clockSignal() }}</div>
  }
</heavy-dashboard>

Technical Implementation Details

The foundation for this feature already exists within Ivy's renderer.

  1. Compiler: The compiler would transform the @isolated block into a standard embedded view (similar to @if), but tag it with a specific flag or a new TViewType (e.g., TViewType.Isolated).
  2. Core / Reactivity: In packages/core/src/render3/reactive_lview_consumer.ts, we can update the viewShouldHaveReactiveConsumer function:
    export function viewShouldHaveReactiveConsumer(tView: TView) {
      // Allow the new isolated block to get its own reactive consumer node
      return tView.type !== TViewType.Embedded || tView.type === TViewType.Isolated;
    }

By allowing this specific embedded view to have its own ReactiveLViewConsumer, signal updates within the block will dirty only that specific node, achieving true fine-grained, localized DOM updates without the overhead of creating a full Angular Component.

Alternatives Considered

  • Extracting to a Component: This is the current workaround. However, creating a new component just for fine-grained reactivity introduces unnecessary boilerplate, input/output wiring, and fragmented logic for what should just be a simple localized UI update.
  • Signal Components: While signal components (if they arrive) might solve this at the component level, the @isolated block solves it elegantly at the template level, providing immediate value for developers migrating to signals in existing large components.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: coreIssues related to the framework runtimegemini-triagedLabel noting that an issue has been triaged by gemini

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions