Commit Graph

52 Commits

Author SHA1 Message Date
Andrew Scott 8735af08b9 feat(router): Add ability to return UrlTree with NavigationBehaviorOptions from guards (#45023)
Returning `UrlTree` from a guard was a convenient new feature added to
the `Router`. However, it does not have feature-parity with the old
`router.navigate(...); return false;` pattern. The most common use-case
for this feature is to redirect to a new page _without_ updating the URL
from the initially attempted navigation. For example, rendering a 404
page when the user does not have access privelages to a route.

Fixes #17004
Fixes #27148

BREAKING CHANGE: Guards can now return `RedirectCommand` for redirects
in addition to `UrlTree`. Code which expects only `boolean` or `UrlTree`
values in `Route` types will need to be adjusted.

PR Close #45023
2024-03-12 09:19:14 -07:00
Andrew Scott 115ee88ba9 fix(router): Navigations triggered by cancellation events should cancel previous navigation (#54710)
There is an edge case where synchronous navigations caused in
response to navigation events can result in a previous navigation not
being unsubscribed from. b/328219996

PR Close #54710
2024-03-07 13:07:08 -08:00
Andrew Scott d3b273ac33 fix(router): Clear internal transition when navigation finalizes (#54261)
This commit fixes a small memory issue in the router where a destroyed
component instance would be retained.

fixes #54241

PR Close #54261
2024-02-21 14:09:52 -08:00
Joey Perrott b857aafcb9 refactor: migrate router to prettier formatting (#54318)
Migrate formatting to prettier for router from clang-format

PR Close #54318
2024-02-08 19:17:14 +00:00
Jessica Janiuk 0dfbde917c Revert "fix(router): Clear internal transition when navigation finalizes (#54261)" (#54317)
This reverts commit 6681292823.

PR Close #54317
2024-02-07 15:46:38 +00:00
Andrew Scott 6681292823 fix(router): Clear internal transition when navigation finalizes (#54261)
This commit fixes a small memory issue in the router where a destroyed
component instance would be retained.

fixes #54241

PR Close #54261
2024-02-06 20:32:34 +00:00
Matthieu Riegler 1c63eddb7c refactor(router): remouve unused (#53750)
minor optimisation, removing unused paramters.

PR Close #53750
2024-01-03 13:29:05 -08:00
Charles Lyding e149ebf228 build: update rxjs build version to v7 (#53500)
The version of rxjs used to build the repository has been updated to v7.
This required only minimal changes to the code. Most of which were type
related only due to more strict types in v7. The behavior in those cases
was left intact. The most common type related change was to handle the
possibility of `undefined` with `toPromise` which was always possible with
v6 but the types did not reflect the runtime behavior. The one change that
was not type related was to provide a parameter value to the `defaultIfEmpty`
operator. It no longer defaults to a value of `null` if no default is provided.
To provide the same behavior the value of `null` is now passed to the operator.

PR Close #53500
2023-12-18 16:25:37 +00:00
Andrew Scott 50d7916278 feat(router): Add router configuration to resolve navigation promise on error (#48910)
With the deprecation of the configurable errorHandler in the Router, there is a missing
use-case to prevent the navigation promise from rejecting on an error. This rejection
results in unhandled promise rejections. This commit allows developers to instruct
the router to instead resolve the navigation promise with 'false', which matches
the behavior of other failed navigations.

Resolving the Promise would be the ideal default behavior. It is rare
that any code handles the navigation Promise at all and even more rare
that the Promise rejection is caught. Updating the default value for
this option should be considered for an upcoming major version.

fixes #48902

PR Close #48910
2023-12-04 21:49:35 -08:00
Andrew Scott 1da28f4825 feat(router): Add callback to execute when a view transition is created (#52002)
This commit adds the ability to provide a function that will get called
immediately after the view transition is created. This will allow
developers to do things like add/remove classes from the DOM when the
transition animation is finished, skip the transition based on
application conditions, etc. Having access to the transition unlocks
just about every example outlined in https://developer.chrome.com/docs/web-platform/view-transitions.

Note that the timing of the `updateCallback` execution is in the spec as
being called asyncronously (https://drafts.csswg.org/css-view-transitions-1/#callbackdef-updatecallback).
This means the `onViewTransitionCreated` callback is guaranteed to
execute before the update callback which in turn means it is guaranteed
to execute before the view transition `ready`/animation. As a result, it
is safe/effictive to add classes to the document in the
`onViewTransitionCreated` function in order to control animations of
that transition and then remove those classes in the transition's `finished`
`Promise`. The animation also doesn't start until the `Promise` returned
by `updateCallback` resolves, so this would also guarantee that the
animation starts asynchronously.

resolves #51827

PR Close #52002
2023-10-10 11:16:22 -07:00
Andrew Scott ad61bf6184 refactor(router): Remove internal state tracking for browserUrlTree (#48065)
The browserUrlTree is only used to support the onSameUrlNavigation: 'ignore' logic. We can achieve this functionality without having this state tracked inside the Router. Instead, we can re-examine what ignore means: We don't want to rerun the matching logic, guards, or resolvers when we already know that nothing is changing.
Outside of the "navigated", there are two things that constitute a "change":

1. The browser URL might change. Because of skipLocationChange, the browser URL might not always match the internal state of the Router (we can navigate to a path but skip updating the browser URL). If we're navigating to a place that would change the browser URL, we should process the navigation. Theoretically, all we need to really do is update the browser URL instead of processing the whole navigation w/ guards, redirects, and resolvers. But this doesn't matter that much because the default value for runGuardsAndResolvers will skip all of this anyways.
2. The internal state of the Router might change. That is, we're navigating to a new path and may or may not be updating the updating the browser URL.

If either of the above are true, we process the navigation. If both are false, we aren't changing anything so we can safely ignore the navigation request (as long as onSameUrlNavigation === 'ignore').

Why is this change important?

* Simplification of Router internals. The Router has a lot of special case handling and one-offs to handle a limited set of scenarios. Removing these when possible makes the code easier to follow

PR Close #48065
2023-09-19 16:50:56 +02:00
Andrew Scott 73e4bf2ed2 feat(router): Add feature to support the View Transitions API (#51314)
The View Transitions API enables easy animations when transitioning between different DOM states. This commit adds an opt-in feature to the Router which runs the component activation and deactivation logic in the document.startViewTransition callback. If the browser does not support this API, route activation and deactivation will happen synchronously.

resolves #49401

PR Close #51314
2023-09-11 10:36:10 -07:00
Andrew Scott b2aff43621 fix(router): Remove urlHandlingStrategy from public Router properties (#51631)
This commit removes the `urlHandlingStrategy` from the public Router's API

BREAKING CHANGE:
`urlHandlingStrategy` has been removed from the Router public API.
This should instead be configured through the provideRouter or RouterModule.forRoot APIs.

PR Close #51631
2023-09-05 17:09:13 +00:00
Andrew Scott 4555290d54 refactor(router): Add a state manager to manage router URL state (#48481)
This commit refactors the router internals to track state inside a separate
`StateManager`. This helps open the door to managing the state in
different, swappable providers. The current interface needed by the
Router is: `currentUrlTree`, `rawUrlTree`, `browserUrlTree`,
`routerState`, and `handleNavigationEvent` (other properties are because
some router properties are writeable when they shouldn't be). This is
a suprisingly small interface and can hopefully be made smaller in the
future (i.e. removing 1 or more of the 3 tracked of `UrlTree`s).

PR Close #48481
2023-09-01 16:12:35 +00:00
Andrew Scott c62e680098 fix(router): Remove deprecated Router properties (#51502)
This commit removes deprecated properties on the Router. These are meant
to be configured through DI and not meant to be changed during runtime.

BREAKING CHANGE: The following Router properties have been removed from
the public API:

- canceledNavigationResolution
- paramsInheritanceStrategy
- titleStrategy
- urlUpdateStrategy
- malformedUriErrorHandler

These should instead be configured through the `provideRouter` or
`RouterModule.forRoot` APIs.

PR Close #51502
2023-08-29 19:47:58 +00:00
Andrew Scott 2aae92b05f refactor(router): Have router subscribe to transition events to update state (#48427)
Rather than the navigation transitions managing Router state, this
commit updates the Router to manage its own state based on ongoing
transition events. In the future, this can be abstracted even further to
have a totally separate class that manages the Router state. This would
allow the potential for swapping state manager implementations rather
than having to implement all types of state management in a single place.

One finding during tests was that unexpected errors thrown by the state management code moved
to the Router here will no longer be caught by the transition pipe's `catchError`.
This only includes calls to the following public Api methods:

* `go`, `replaceState`, `historyGo`, `isCurrentPathEqualTo` on `Location`
* `UrlSerializer.serialize`
* `UrlHandlingStrategy.merge`.

None of these methods should throw if the router is expected to function.
These might throw when tests include incomplete mocks, which is not
supported, or in cases where the actual browser methods like
`replaceState` would throw. This will already result in unexpected/unsupported
behavior. The failure case here is now arguably better - the navigation
itself still completes but the state update (either updating Router
internal state or updating the browser URL) fails separately and is
unhandled.

PR Close #48427
2023-08-22 08:04:00 -07:00
Matthieu Riegler 9209692bde docs(router): Make links out of @see tags (#50110)
This commit is part of the work for #50097 to improve the linking on the online documentation.

PR Close #50110
2023-06-14 10:54:38 +02:00
Andrew Scott 3c65305b10 refactor(router): remove targetPageId from transition (#49799)
The `targetPageId` was pre-calculated at the start of a navigation using
the same logic that exists in `setBrowserUrl` now. Doing the calculation
ahead of time is not necessary and complicates the transition state.

PR Close #49799
2023-04-17 17:36:02 +00:00
Andrew Scott fa3909e8b4 fix(router): Ensure initial navigation clears current navigation when blocking (#49572)
The navigation transition clears the current navigation in the finalize
operator of the current navigation Observer. This commit both completes
the `bootstrapDone` observable and updates the transition to only take 1
emit from the completed navigation. Either of these changes on their own
would fix the issue. The latter is a preventative measure in case a
mistake like the former is made again.

fixes #49567

PR Close #49572
2023-03-31 17:04:01 -07:00
Andrew Scott f982a3f965 feat(router): Opt-in for binding Router information to component inputs (#49633)
Adds ability for `RouterOutlet` to bind `Router` information to the routed
component's inputs. This commit also exposes some helpers for
implementers of custom outlets to do their own input binding if desired.

Resolves #18967

PR Close #49633
2023-03-30 16:10:54 -07:00
Andrew Scott 3c7e637374 fix(router): Route matching should only happen once when navigating (#49163)
When navigating in the Router, the current approach does the redirects
and the creation of the `RouterStateSnapshot` in two separate steps
(applyRedirects and recognize). These two steps duplicate the route
matching logic, resulting in user code on routes being executing twice
(custom `UrlMatcher` and `canMatch` guards). This also duplicates the
complex matching logic in two places, which increases the bundle size
and maintenance burden.

This commit combines the `applyRedirects` and `recognize` steps into a
single matching algorithm.

fixes #26081

PR Close #49163
2023-03-29 14:40:41 -07:00
Andrew Scott 0432d952a1 Revert "fix(router): Route matching should only happen once when navigating (#49163)" (#49634)
This reverts commit 1600687fe5.

PR Close #49634
2023-03-29 11:37:29 -07:00
Andrew Scott 1600687fe5 fix(router): Route matching should only happen once when navigating (#49163)
When navigating in the Router, the current approach does the redirects
and the creation of the `RouterStateSnapshot` in two separate steps
(applyRedirects and recognize). These two steps duplicate the route
matching logic, resulting in user code on routes being executing twice
(custom `UrlMatcher` and `canMatch` guards). This also duplicates the
complex matching logic in two places, which increases the bundle size
and maintenance burden.

This commit combines the `applyRedirects` and `recognize` steps into a
single matching algorithm.

fixes #26081

PR Close #49163
2023-03-28 13:53:57 -07:00
Andrew Scott 8d91d74d46 refactor(core): Remove NG_DEV_MODE const (#49530)
From Joost: The locally defined NG_DEV_MODE does not work with ESBuild, as it doesn’t fold recursively

PR Close #49530
2023-03-22 15:31:48 -07:00
ced 5bb1223737 refactor(router): remove unused parameter in navigation internal function (#48724)
The internal `cancelNavigationTransition` required an unused `router` parameter.

PR Close #48724
2023-01-13 10:37:25 -08:00
Andrew Scott a3a4ca0b00 refactor(router): move internal router properties to transition handler where appropriate (#48475)
Working towards removing the backwards dependency on router from the
navigation transition handler, this change moves `rootComponentType` and
`afterPreactivation` to the transition handler since that is the only
location those properties are used.

PR Close #48475
2023-01-10 07:59:16 -08:00
Andrew Scott cb6d73a84e fix(router): page refresh should not destroy history state (#48540)
The router's `initialNavigation` causes an imperative navigation using
the `navigateByUrl` method. This, however, results in the history state
being removed on a page refresh. This change calls `scheduleNavigation`
directly from `initialNavigation` to ensure the history state is correctly
retained.

PR Close #48540
2023-01-05 14:50:53 -08:00
Matthieu Riegler 0fa70dfb6d refactor(router): code cleaning (#48259)
Removing unnecessary type assertions, null assertions etc.

PR Close #48259
2022-12-09 09:59:20 -08:00
Andrew Scott 0ff5d972cd refactor(router): Move navigationId handling to the transition manager (#48202)
The navigationId is really just a count of how many navigations have been
processed through the navigation pipeline. This tracking should be
done as part of the navigation transition handler

PR Close #48202
2022-11-29 14:55:25 -08:00
Andrew Scott 55ae4aa234 refactor(router): Move transition subject into transition handler (#48202)
The navigation transitions subject belongs in the navigation transitions handler
rather than the Router.

PR Close #48202
2022-11-29 14:55:25 -08:00
Andrew Scott edd5192264 refactor(router): directly inject internal properties from DI (#48202)
Rather than accessing router internal properties that are available in DI,
this commit directly injects those dependencies in the navigation transition
handler. Note that there are several other items that _should_ be injectable
in DI (like the TitleStrategy) but because those are part of the Router public
interface and writeable(!), they might be changed during runtime. We
have to get these other items from the Router for now...

PR Close #48202
2022-11-29 14:55:25 -08:00
Andrew Scott 17b76998ae refactor(router): Get EnvironmentInjector directly in transition handler (#48202)
Remove the NgModuleRef from the internal interface of the Router. This
was only used to get the injector (equivalent to EnvironmentInjector).
Instead, the navigation transition handler can directly inject the
EnvironmentInjector

PR Close #48202
2022-11-29 14:55:25 -08:00
Andrew Scott 7b1d63e939 refactor(router): Move configLoader to transition handler (#48202)
The ConfigLoader is only used as part of the navigation transition.
Moving the loader there completes the removal of event triggering in
the router code. This all now lives in the transition handler (plus
the router scroller, but let's ignore that...).

PR Close #48202
2022-11-29 14:55:25 -08:00
Andrew Scott 6810a04143 refactor(router): Move events subject to transition class (#48202)
The events observable is part of the lifecycle of a navigation. This should
be contained in the NavigationTransitions class rather than the Router.
This Subject is re-exported by the router as an observable to maintain
the public API

PR Close #48202
2022-11-29 14:55:25 -08:00
Andrew Scott b02df19934 refactor(router): remove malformedUriHandler from interface passed to transitions (#48202)
The malformedUriHandler is not used during the navigation transition and can be removed form the interface

PR Close #48202
2022-11-29 14:55:25 -08:00
Andrew Scott aa66f703d2 Revert "refactor(router): remove malformedUriHandler from interface passed to transitions (#48202)" (#48269)
This reverts commit 17aba7c4c0.

PR Close #48269
2022-11-28 16:52:08 -08:00
Andrew Scott db1c73c431 Revert "refactor(router): Move events subject to transition class (#48202)" (#48269)
This reverts commit f555050f9a.

PR Close #48269
2022-11-28 16:52:07 -08:00
Andrew Scott a765876f97 Revert "refactor(router): Move configLoader to transition handler (#48202)" (#48269)
This reverts commit bec2e79e81.

PR Close #48269
2022-11-28 16:52:07 -08:00
Andrew Scott 5a1bb6d595 Revert "refactor(router): Get EnvironmentInjector directly in transition handler (#48202)" (#48269)
This reverts commit 008a1b0e44.

PR Close #48269
2022-11-28 16:52:07 -08:00
Andrew Scott 7a23ba99b5 Revert "refactor(router): directly inject internal properties from DI (#48202)" (#48269)
This reverts commit b17dc7a7f7.

PR Close #48269
2022-11-28 16:52:07 -08:00
Andrew Scott 98abd61643 Revert "refactor(router): Move transition subject into transition handler (#48202)" (#48269)
This reverts commit ca6b766e47.

PR Close #48269
2022-11-28 16:52:07 -08:00
Andrew Scott 88ccc75cc4 Revert "refactor(router): Move navigationId handling to the transition manager (#48202)" (#48269)
This reverts commit afc668acd5.

PR Close #48269
2022-11-28 16:52:07 -08:00
Andrew Scott afc668acd5 refactor(router): Move navigationId handling to the transition manager (#48202)
The navigationId is really just a count of how many navigations have been
processed through the navigation pipeline. This tracking should be
done as part of the navigation transition handler

PR Close #48202
2022-11-28 10:53:26 -08:00
Andrew Scott ca6b766e47 refactor(router): Move transition subject into transition handler (#48202)
The navigation transitions subject belongs in the navigation transitions handler
rather than the Router.

PR Close #48202
2022-11-28 10:53:26 -08:00
Andrew Scott b17dc7a7f7 refactor(router): directly inject internal properties from DI (#48202)
Rather than accessing router internal properties that are available in DI,
this commit directly injects those dependencies in the navigation transition
handler. Note that there are several other items that _should_ be injectable
in DI (like the TitleStrategy) but because those are part of the Router public
interface and writeable(!), they might be changed during runtime. We
have to get these other items from the Router for now...

PR Close #48202
2022-11-28 10:53:26 -08:00
Andrew Scott 008a1b0e44 refactor(router): Get EnvironmentInjector directly in transition handler (#48202)
Remove the NgModuleRef from the internal interface of the Router. This
was only used to get the injector (equivalent to EnvironmentInjector).
Instead, the navigation transition handler can directly inject the
EnvironmentInjector

PR Close #48202
2022-11-28 10:53:26 -08:00
Andrew Scott bec2e79e81 refactor(router): Move configLoader to transition handler (#48202)
The ConfigLoader is only used as part of the navigation transition.
Moving the loader there completes the removal of event triggering in
the router code. This all now lives in the transition handler (plus
the router scroller, but let's ignore that...).

PR Close #48202
2022-11-28 10:53:26 -08:00
Andrew Scott f555050f9a refactor(router): Move events subject to transition class (#48202)
The events observable is part of the lifecycle of a navigation. This should
be contained in the NavigationTransitions class rather than the Router.
This Subject is re-exported by the router as an observable to maintain
the public API

PR Close #48202
2022-11-28 10:53:26 -08:00
Andrew Scott 17aba7c4c0 refactor(router): remove malformedUriHandler from interface passed to transitions (#48202)
The malformedUriHandler is not used during the navigation transition and can be removed form the interface

PR Close #48202
2022-11-28 10:53:26 -08:00
Andrew Scott 3000f90632 refactor(router): move lastSuccesfulNavigation to navigation transitions (#48202)
lastSuccessfulNavigation is only used in the transition so it does not need to live in Router

PR Close #48202
2022-11-28 10:53:26 -08:00