Skip to content

refactor(router): Create transactional router resource#69490

Open
atscott wants to merge 1 commit into
angular:mainfrom
atscott:routerresourceimpl
Open

refactor(router): Create transactional router resource#69490
atscott wants to merge 1 commit into
angular:mainfrom
atscott:routerresourceimpl

Conversation

@atscott

@atscott atscott commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

This commit adds an implementation of a router resource (not currently exposed for public use) which
defines the behavior of a resource dependent on the Router navigation lifecycle.

The cooperative router resource has the following behaviors:

  • Universal Resource Support: Because the wrapper operates on the standard Resource<T> base interface, it natively and transparently supports wrapping any compliant resource implementation (such as resource() or rxResource()) out-of-the-box.
  • Transactional Freezing: During navigation, the state of the resource (value, status, error, and loading signals) is frozen so the application state and UI do not eagerly change/flash during an in-progress navigation.
  • Rollback Recovery: On a true rollback cancellation, it retains the frozen snapshot (to prevent a loading flash of the previous state) until the resource successfully finishes reloading the rolled-back state.
  • Immediate Recovery Cancellation: If the frozen state was not a valid settled state (e.g. was in 'error'), it bypasses the recovery phase and unfreezes immediately on rollback.
  • New Navigation Preemption: Starting a new navigation immediately preempts and clears any pending rollback recovery.
  • Cooperative API Surface: It omits writable APIs (set/update) to prevent out-of-band mutations that bypass the transactional freeze, and only exposes a minification-safe reload() method that is disabled during active navigations.

@ngbot ngbot Bot added this to the Backlog milestone Jun 23, 2026
@atscott atscott added the target: patch This PR is targeted for the next patch release label Jun 23, 2026
@atscott atscott marked this pull request as ready for review June 23, 2026 20:31
@atscott atscott requested review from alxhub and leonsenft June 23, 2026 20:32

@JeanMeche JeanMeche left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a few comments

Comment thread packages/router/src/router_resource.ts
injector,
);

const res = resourceFromSnapshots(snapshotSignal) as Resource<T> & {reload(): boolean};

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Side conversation, this reminds me of #67124. We might want to have such feature in the public api.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, it's a bit of that which seems to also be a consequence of Resource not having reload. It's only on WritableResource but it feels to me like reload is quite different from the set of WritableResource and could arguably be in the base Resource interface

Comment thread packages/router/test/router_resource_behavior_spec.ts Outdated
Comment thread packages/router/test/router_resource_behavior_spec.ts Outdated
@atscott atscott force-pushed the routerresourceimpl branch 3 times, most recently from 0f1ba79 to 76aa561 Compare June 23, 2026 21:53
This commit adds an implementation of a router resource (not currently exposed for public use) which
defines the behavior of a resource dependent on the Router navigation lifecycle.

The cooperative router resource has the following behaviors:

* **Universal Resource Support**: Because the wrapper operates on the standard `Resource<T>` base interface, it natively and transparently supports wrapping any compliant resource implementation (such as `resource()` or `rxResource()`) out-of-the-box.
* **Transactional Freezing**: During navigation, the state of the resource (value, status, error, and loading signals) is frozen so the application state and UI do not eagerly change/flash during an in-progress navigation.
* **Rollback Recovery**: On a true rollback cancellation, it retains the frozen snapshot (to prevent a loading flash of the previous state) until the resource successfully finishes reloading the rolled-back state.
* **Immediate Recovery Cancellation**: If the frozen state was not a valid settled state (e.g. was in 'error'), it bypasses the recovery phase and unfreezes immediately on rollback.
* **New Navigation Preemption**: Starting a new navigation immediately preempts and clears any pending rollback recovery.
* **Cooperative API Surface**: It omits writable APIs (set/update) to prevent out-of-band mutations that bypass the transactional freeze, and only exposes a minification-safe `reload()` method that is disabled during active navigations.
@atscott atscott force-pushed the routerresourceimpl branch from 76aa561 to e39a22b Compare June 23, 2026 21:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: router target: patch This PR is targeted for the next patch release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants