@angular/router 17.0.0-next.1 → 17.0.0-next.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v17.0.0-next.1
2
+ * @license Angular v17.0.0-next.3
3
3
  * (c) 2010-2022 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
@@ -114,8 +114,8 @@ function shallowEqualArrays(a, b) {
114
114
  function shallowEqual(a, b) {
115
115
  // While `undefined` should never be possible, it would sometimes be the case in IE 11
116
116
  // and pre-chromium Edge. The check below accounts for this edge case.
117
- const k1 = a ? Object.keys(a) : undefined;
118
- const k2 = b ? Object.keys(b) : undefined;
117
+ const k1 = a ? getDataKeys(a) : undefined;
118
+ const k2 = b ? getDataKeys(b) : undefined;
119
119
  if (!k1 || !k2 || k1.length != k2.length) {
120
120
  return false;
121
121
  }
@@ -128,6 +128,12 @@ function shallowEqual(a, b) {
128
128
  }
129
129
  return true;
130
130
  }
131
+ /**
132
+ * Gets the keys of an object, including `symbol` keys.
133
+ */
134
+ function getDataKeys(obj) {
135
+ return [...Object.keys(obj), ...Object.getOwnPropertySymbols(obj)];
136
+ }
131
137
  /**
132
138
  * Test equality for arrays of strings or a string.
133
139
  */
@@ -419,10 +425,10 @@ function mapChildrenIntoArray(segment, fn) {
419
425
  * @publicApi
420
426
  */
421
427
  class UrlSerializer {
422
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: UrlSerializer, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
423
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: UrlSerializer, providedIn: 'root', useFactory: () => new DefaultUrlSerializer() }); }
428
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: UrlSerializer, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
429
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: UrlSerializer, providedIn: 'root', useFactory: () => new DefaultUrlSerializer() }); }
424
430
  }
425
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: UrlSerializer, decorators: [{
431
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: UrlSerializer, decorators: [{
426
432
  type: Injectable,
427
433
  args: [{ providedIn: 'root', useFactory: () => new DefaultUrlSerializer() }]
428
434
  }] });
@@ -1779,10 +1785,10 @@ class ChildrenOutletContexts {
1779
1785
  getContext(childName) {
1780
1786
  return this.contexts.get(childName) || null;
1781
1787
  }
1782
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: ChildrenOutletContexts, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1783
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: ChildrenOutletContexts, providedIn: 'root' }); }
1788
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: ChildrenOutletContexts, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1789
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: ChildrenOutletContexts, providedIn: 'root' }); }
1784
1790
  }
1785
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: ChildrenOutletContexts, decorators: [{
1791
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: ChildrenOutletContexts, decorators: [{
1786
1792
  type: Injectable,
1787
1793
  args: [{ providedIn: 'root' }]
1788
1794
  }] });
@@ -2489,10 +2495,10 @@ class RouterOutlet {
2489
2495
  this.inputBinder?.bindActivatedRouteToOutletComponent(this);
2490
2496
  this.activateEvents.emit(this.activated.instance);
2491
2497
  }
2492
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: RouterOutlet, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2493
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.0-next.1", type: RouterOutlet, isStandalone: true, selector: "router-outlet", inputs: { name: "name" }, outputs: { activateEvents: "activate", deactivateEvents: "deactivate", attachEvents: "attach", detachEvents: "detach" }, exportAs: ["outlet"], usesOnChanges: true, ngImport: i0 }); }
2498
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: RouterOutlet, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2499
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.0-next.3", type: RouterOutlet, isStandalone: true, selector: "router-outlet", inputs: { name: "name" }, outputs: { activateEvents: "activate", deactivateEvents: "deactivate", attachEvents: "attach", detachEvents: "detach" }, exportAs: ["outlet"], usesOnChanges: true, ngImport: i0 }); }
2494
2500
  }
2495
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: RouterOutlet, decorators: [{
2501
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: RouterOutlet, decorators: [{
2496
2502
  type: Directive,
2497
2503
  args: [{
2498
2504
  selector: 'router-outlet',
@@ -2595,10 +2601,10 @@ class RoutedComponentInputBinder {
2595
2601
  });
2596
2602
  this.outletDataSubscriptions.set(outlet, dataSubscription);
2597
2603
  }
2598
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: RoutedComponentInputBinder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2599
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: RoutedComponentInputBinder }); }
2604
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: RoutedComponentInputBinder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2605
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: RoutedComponentInputBinder }); }
2600
2606
  }
2601
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: RoutedComponentInputBinder, decorators: [{
2607
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: RoutedComponentInputBinder, decorators: [{
2602
2608
  type: Injectable
2603
2609
  }] });
2604
2610
 
@@ -2678,10 +2684,10 @@ function isNavigationCancelingError$1(error) {
2678
2684
  * to this `EmptyOutletComponent`.
2679
2685
  */
2680
2686
  class ɵEmptyOutletComponent {
2681
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: ɵEmptyOutletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2682
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.0.0-next.1", type: ɵEmptyOutletComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: `<router-outlet></router-outlet>`, isInline: true, dependencies: [{ kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }] }); }
2687
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: ɵEmptyOutletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2688
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.0.0-next.3", type: ɵEmptyOutletComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: `<router-outlet></router-outlet>`, isInline: true, dependencies: [{ kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }] }); }
2683
2689
  }
2684
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: ɵEmptyOutletComponent, decorators: [{
2690
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: ɵEmptyOutletComponent, decorators: [{
2685
2691
  type: Component,
2686
2692
  args: [{
2687
2693
  template: `<router-outlet></router-outlet>`,
@@ -3419,8 +3425,9 @@ class NoMatch {
3419
3425
  this.segmentGroup = segmentGroup || null;
3420
3426
  }
3421
3427
  }
3422
- class AbsoluteRedirect {
3428
+ class AbsoluteRedirect extends Error {
3423
3429
  constructor(urlTree) {
3430
+ super();
3424
3431
  this.urlTree = urlTree;
3425
3432
  }
3426
3433
  }
@@ -3462,7 +3469,11 @@ class ApplyRedirects {
3462
3469
  }
3463
3470
  }
3464
3471
  applyRedirectCommands(segments, redirectTo, posParams) {
3465
- return this.applyRedirectCreateUrlTree(redirectTo, this.urlSerializer.parse(redirectTo), segments, posParams);
3472
+ const newTree = this.applyRedirectCreateUrlTree(redirectTo, this.urlSerializer.parse(redirectTo), segments, posParams);
3473
+ if (redirectTo.startsWith('/')) {
3474
+ throw new AbsoluteRedirect(newTree);
3475
+ }
3476
+ return newTree;
3466
3477
  }
3467
3478
  applyRedirectCreateUrlTree(redirectTo, urlTree, segments, posParams) {
3468
3479
  const newRoot = this.createSegmentGroup(redirectTo, urlTree.root, segments, posParams);
@@ -3642,6 +3653,13 @@ function noLeftoversInUrl(segmentGroup, segments, outlet) {
3642
3653
  return segments.length === 0 && !segmentGroup.children[outlet];
3643
3654
  }
3644
3655
 
3656
+ /**
3657
+ * Class used to indicate there were no additional route config matches but that all segments of
3658
+ * the URL were consumed during matching so the route was URL matched. When this happens, we still
3659
+ * try to match child configs in case there are empty path children.
3660
+ */
3661
+ class NoLeftoversInUrl {
3662
+ }
3645
3663
  function recognize$1(injector, configLoader, rootComponentType, config, urlTree, urlSerializer, paramsInheritanceStrategy = 'emptyOnly') {
3646
3664
  return new Recognizer(injector, configLoader, rootComponentType, config, urlTree, paramsInheritanceStrategy, urlSerializer)
3647
3665
  .recognize();
@@ -3713,7 +3731,8 @@ class Recognizer {
3713
3731
  if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) {
3714
3732
  return this.processChildren(injector, config, segmentGroup);
3715
3733
  }
3716
- return this.processSegment(injector, config, segmentGroup, segmentGroup.segments, outlet, true);
3734
+ return this.processSegment(injector, config, segmentGroup, segmentGroup.segments, outlet, true)
3735
+ .pipe(map(child => child instanceof TreeNode ? [child] : []));
3717
3736
  }
3718
3737
  /**
3719
3738
  * Matches every child outlet in the `segmentGroup` to a `Route` in the config. Returns `null` if
@@ -3775,7 +3794,7 @@ class Recognizer {
3775
3794
  }), first((x) => !!x), catchError(e => {
3776
3795
  if (isEmptyError(e)) {
3777
3796
  if (noLeftoversInUrl(segmentGroup, segments, outlet)) {
3778
- return of([]);
3797
+ return of(new NoLeftoversInUrl());
3779
3798
  }
3780
3799
  return noMatch$1(segmentGroup);
3781
3800
  }
@@ -3786,7 +3805,7 @@ class Recognizer {
3786
3805
  if (!isImmediateMatch(route, rawSegment, segments, outlet))
3787
3806
  return noMatch$1(rawSegment);
3788
3807
  if (route.redirectTo === undefined) {
3789
- return this.matchSegmentAgainstRoute(injector, rawSegment, route, segments, outlet, allowRedirects);
3808
+ return this.matchSegmentAgainstRoute(injector, rawSegment, route, segments, outlet);
3790
3809
  }
3791
3810
  if (allowRedirects && this.allowRedirects) {
3792
3811
  return this.expandSegmentAgainstRouteUsingRedirect(injector, rawSegment, routes, route, segments, outlet);
@@ -3794,45 +3813,20 @@ class Recognizer {
3794
3813
  return noMatch$1(rawSegment);
3795
3814
  }
3796
3815
  expandSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet) {
3797
- if (route.path === '**') {
3798
- return this.expandWildCardWithParamsAgainstRouteUsingRedirect(injector, routes, route, outlet);
3799
- }
3800
- return this.expandRegularSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet);
3801
- }
3802
- expandWildCardWithParamsAgainstRouteUsingRedirect(injector, routes, route, outlet) {
3803
- const newTree = this.applyRedirects.applyRedirectCommands([], route.redirectTo, {});
3804
- if (route.redirectTo.startsWith('/')) {
3805
- return absoluteRedirect(newTree);
3806
- }
3807
- return this.applyRedirects.lineralizeSegments(route, newTree)
3808
- .pipe(mergeMap((newSegments) => {
3809
- const group = new UrlSegmentGroup(newSegments, {});
3810
- return this.processSegment(injector, routes, group, newSegments, outlet, false);
3811
- }));
3812
- }
3813
- expandRegularSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet) {
3814
- const { matched, consumedSegments, remainingSegments, positionalParamSegments } = match(segmentGroup, route, segments);
3816
+ const { matched, consumedSegments, positionalParamSegments, remainingSegments, } = route.path === '**' ? createWildcardMatchResult(segments) :
3817
+ match(segmentGroup, route, segments);
3815
3818
  if (!matched)
3816
3819
  return noMatch$1(segmentGroup);
3817
3820
  const newTree = this.applyRedirects.applyRedirectCommands(consumedSegments, route.redirectTo, positionalParamSegments);
3818
- if (route.redirectTo.startsWith('/')) {
3819
- return absoluteRedirect(newTree);
3820
- }
3821
3821
  return this.applyRedirects.lineralizeSegments(route, newTree)
3822
3822
  .pipe(mergeMap((newSegments) => {
3823
3823
  return this.processSegment(injector, routes, segmentGroup, newSegments.concat(remainingSegments), outlet, false);
3824
3824
  }));
3825
3825
  }
3826
- matchSegmentAgainstRoute(injector, rawSegment, route, segments, outlet, allowRedirects) {
3826
+ matchSegmentAgainstRoute(injector, rawSegment, route, segments, outlet) {
3827
3827
  let matchResult;
3828
3828
  if (route.path === '**') {
3829
- const params = segments.length > 0 ? last(segments).parameters : {};
3830
- const snapshot = new ActivatedRouteSnapshot(segments, params, Object.freeze({ ...this.urlTree.queryParams }), this.urlTree.fragment, getData(route), getOutlet(route), route.component ?? route._loadedComponent ?? null, route, getResolve(route));
3831
- matchResult = of({
3832
- snapshot,
3833
- consumedSegments: [],
3834
- remainingSegments: [],
3835
- });
3829
+ matchResult = of(createWildcardMatchResult(segments));
3836
3830
  // Prior versions of the route matching algorithm would stop matching at the wildcard route.
3837
3831
  // We should investigate a better strategy for any existing children. Otherwise, these
3838
3832
  // child segments are silently dropped from the navigation.
@@ -3840,18 +3834,10 @@ class Recognizer {
3840
3834
  rawSegment.children = {};
3841
3835
  }
3842
3836
  else {
3843
- matchResult =
3844
- matchWithChecks(rawSegment, route, segments, injector, this.urlSerializer)
3845
- .pipe(map(({ matched, consumedSegments, remainingSegments, parameters }) => {
3846
- if (!matched) {
3847
- return null;
3848
- }
3849
- const snapshot = new ActivatedRouteSnapshot(consumedSegments, parameters, Object.freeze({ ...this.urlTree.queryParams }), this.urlTree.fragment, getData(route), getOutlet(route), route.component ?? route._loadedComponent ?? null, route, getResolve(route));
3850
- return { snapshot, consumedSegments, remainingSegments };
3851
- }));
3837
+ matchResult = matchWithChecks(rawSegment, route, segments, injector, this.urlSerializer);
3852
3838
  }
3853
3839
  return matchResult.pipe(switchMap((result) => {
3854
- if (result === null) {
3840
+ if (!result.matched) {
3855
3841
  return noMatch$1(rawSegment);
3856
3842
  }
3857
3843
  // If the route has an injector created from providers, we should start using that.
@@ -3859,7 +3845,8 @@ class Recognizer {
3859
3845
  return this.getChildConfig(injector, route, segments)
3860
3846
  .pipe(switchMap(({ routes: childConfig }) => {
3861
3847
  const childInjector = route._loadedInjector ?? injector;
3862
- const { snapshot, consumedSegments, remainingSegments } = result;
3848
+ const { consumedSegments, remainingSegments, parameters } = result;
3849
+ const snapshot = new ActivatedRouteSnapshot(consumedSegments, parameters, Object.freeze({ ...this.urlTree.queryParams }), this.urlTree.fragment, getData(route), getOutlet(route), route.component ?? route._loadedComponent ?? null, route, getResolve(route));
3863
3850
  const { segmentGroup, slicedSegments } = split(rawSegment, consumedSegments, remainingSegments, childConfig);
3864
3851
  if (slicedSegments.length === 0 && segmentGroup.hasChildren()) {
3865
3852
  return this.processChildren(childInjector, childConfig, segmentGroup)
@@ -3867,11 +3854,11 @@ class Recognizer {
3867
3854
  if (children === null) {
3868
3855
  return null;
3869
3856
  }
3870
- return [new TreeNode(snapshot, children)];
3857
+ return new TreeNode(snapshot, children);
3871
3858
  }));
3872
3859
  }
3873
3860
  if (childConfig.length === 0 && slicedSegments.length === 0) {
3874
- return of([new TreeNode(snapshot, [])]);
3861
+ return of(new TreeNode(snapshot, []));
3875
3862
  }
3876
3863
  const matchedOnOutlet = getOutlet(route) === outlet;
3877
3864
  // If we matched a config due to empty path match on a different outlet, we need to
@@ -3884,8 +3871,8 @@ class Recognizer {
3884
3871
  // Notice that the children of the named outlet are configured with the primary outlet
3885
3872
  return this
3886
3873
  .processSegment(childInjector, childConfig, segmentGroup, slicedSegments, matchedOnOutlet ? PRIMARY_OUTLET : outlet, true)
3887
- .pipe(map(children => {
3888
- return [new TreeNode(snapshot, children)];
3874
+ .pipe(map(child => {
3875
+ return new TreeNode(snapshot, child instanceof TreeNode ? [child] : []);
3889
3876
  }));
3890
3877
  }));
3891
3878
  }));
@@ -3980,6 +3967,15 @@ function getData(route) {
3980
3967
  function getResolve(route) {
3981
3968
  return route.resolve || {};
3982
3969
  }
3970
+ function createWildcardMatchResult(segments) {
3971
+ return {
3972
+ matched: true,
3973
+ parameters: segments.length > 0 ? last(segments).parameters : {},
3974
+ consumedSegments: segments,
3975
+ remainingSegments: [],
3976
+ positionalParamSegments: {},
3977
+ };
3978
+ }
3983
3979
 
3984
3980
  function recognize(injector, configLoader, rootComponentType, config, serializer, paramsInheritanceStrategy) {
3985
3981
  return mergeMap(t => recognize$1(injector, configLoader, rootComponentType, config, t.extractedUrl, serializer, paramsInheritanceStrategy)
@@ -4025,9 +4021,6 @@ function resolveNode(resolve, futureARS, futureRSS, injector) {
4025
4021
  data[key] = value;
4026
4022
  }))), takeLast(1), mapTo(data), catchError((e) => isEmptyError(e) ? EMPTY : throwError(e)));
4027
4023
  }
4028
- function getDataKeys(obj) {
4029
- return [...Object.keys(obj), ...Object.getOwnPropertySymbols(obj)];
4030
- }
4031
4024
  function getResolver(injectionToken, futureARS, futureRSS, injector) {
4032
4025
  const closestInjector = getClosestRouteInjector(futureARS) ?? injector;
4033
4026
  const resolver = getTokenOrFunctionIdentity(injectionToken, closestInjector);
@@ -4056,6 +4049,93 @@ function switchTap(next) {
4056
4049
  });
4057
4050
  }
4058
4051
 
4052
+ /**
4053
+ * Provides a strategy for setting the page title after a router navigation.
4054
+ *
4055
+ * The built-in implementation traverses the router state snapshot and finds the deepest primary
4056
+ * outlet with `title` property. Given the `Routes` below, navigating to
4057
+ * `/base/child(popup:aux)` would result in the document title being set to "child".
4058
+ * ```
4059
+ * [
4060
+ * {path: 'base', title: 'base', children: [
4061
+ * {path: 'child', title: 'child'},
4062
+ * ],
4063
+ * {path: 'aux', outlet: 'popup', title: 'popupTitle'}
4064
+ * ]
4065
+ * ```
4066
+ *
4067
+ * This class can be used as a base class for custom title strategies. That is, you can create your
4068
+ * own class that extends the `TitleStrategy`. Note that in the above example, the `title`
4069
+ * from the named outlet is never used. However, a custom strategy might be implemented to
4070
+ * incorporate titles in named outlets.
4071
+ *
4072
+ * @publicApi
4073
+ * @see [Page title guide](guide/router#setting-the-page-title)
4074
+ */
4075
+ class TitleStrategy {
4076
+ /**
4077
+ * @returns The `title` of the deepest primary route.
4078
+ */
4079
+ buildTitle(snapshot) {
4080
+ let pageTitle;
4081
+ let route = snapshot.root;
4082
+ while (route !== undefined) {
4083
+ pageTitle = this.getResolvedTitleForRoute(route) ?? pageTitle;
4084
+ route = route.children.find(child => child.outlet === PRIMARY_OUTLET);
4085
+ }
4086
+ return pageTitle;
4087
+ }
4088
+ /**
4089
+ * Given an `ActivatedRouteSnapshot`, returns the final value of the
4090
+ * `Route.title` property, which can either be a static string or a resolved value.
4091
+ */
4092
+ getResolvedTitleForRoute(snapshot) {
4093
+ return snapshot.data[RouteTitleKey];
4094
+ }
4095
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: TitleStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4096
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: TitleStrategy, providedIn: 'root', useFactory: () => inject(DefaultTitleStrategy) }); }
4097
+ }
4098
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: TitleStrategy, decorators: [{
4099
+ type: Injectable,
4100
+ args: [{ providedIn: 'root', useFactory: () => inject(DefaultTitleStrategy) }]
4101
+ }] });
4102
+ /**
4103
+ * The default `TitleStrategy` used by the router that updates the title using the `Title` service.
4104
+ */
4105
+ class DefaultTitleStrategy extends TitleStrategy {
4106
+ constructor(title) {
4107
+ super();
4108
+ this.title = title;
4109
+ }
4110
+ /**
4111
+ * Sets the title of the browser to the given value.
4112
+ *
4113
+ * @param title The `pageTitle` from the deepest primary route.
4114
+ */
4115
+ updateTitle(snapshot) {
4116
+ const title = this.buildTitle(snapshot);
4117
+ if (title !== undefined) {
4118
+ this.title.setTitle(title);
4119
+ }
4120
+ }
4121
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: DefaultTitleStrategy, deps: [{ token: i1.Title }], target: i0.ɵɵFactoryTarget.Injectable }); }
4122
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: DefaultTitleStrategy, providedIn: 'root' }); }
4123
+ }
4124
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: DefaultTitleStrategy, decorators: [{
4125
+ type: Injectable,
4126
+ args: [{ providedIn: 'root' }]
4127
+ }], ctorParameters: function () { return [{ type: i1.Title }]; } });
4128
+
4129
+ /**
4130
+ * A [DI token](guide/glossary/#di-token) for the router service.
4131
+ *
4132
+ * @publicApi
4133
+ */
4134
+ const ROUTER_CONFIGURATION = new InjectionToken((typeof ngDevMode === 'undefined' || ngDevMode) ? 'router config' : '', {
4135
+ providedIn: 'root',
4136
+ factory: () => ({}),
4137
+ });
4138
+
4059
4139
  /**
4060
4140
  * The [DI token](guide/glossary/#di-token) for a router configuration.
4061
4141
  *
@@ -4155,10 +4235,10 @@ class RouterConfigLoader {
4155
4235
  }
4156
4236
  }));
4157
4237
  }
4158
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: RouterConfigLoader, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4159
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: RouterConfigLoader, providedIn: 'root' }); }
4238
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: RouterConfigLoader, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4239
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: RouterConfigLoader, providedIn: 'root' }); }
4160
4240
  }
4161
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: RouterConfigLoader, decorators: [{
4241
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: RouterConfigLoader, decorators: [{
4162
4242
  type: Injectable,
4163
4243
  args: [{ providedIn: 'root' }]
4164
4244
  }] });
@@ -4174,6 +4254,42 @@ function maybeUnwrapDefaultExport(input) {
4174
4254
  return isWrappedDefaultExport(input) ? input['default'] : input;
4175
4255
  }
4176
4256
 
4257
+ /**
4258
+ * @description
4259
+ *
4260
+ * Provides a way to migrate AngularJS applications to Angular.
4261
+ *
4262
+ * @publicApi
4263
+ */
4264
+ class UrlHandlingStrategy {
4265
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: UrlHandlingStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4266
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: UrlHandlingStrategy, providedIn: 'root', useFactory: () => inject(DefaultUrlHandlingStrategy) }); }
4267
+ }
4268
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: UrlHandlingStrategy, decorators: [{
4269
+ type: Injectable,
4270
+ args: [{ providedIn: 'root', useFactory: () => inject(DefaultUrlHandlingStrategy) }]
4271
+ }] });
4272
+ /**
4273
+ * @publicApi
4274
+ */
4275
+ class DefaultUrlHandlingStrategy {
4276
+ shouldProcessUrl(url) {
4277
+ return true;
4278
+ }
4279
+ extract(url) {
4280
+ return url;
4281
+ }
4282
+ merge(newUrlPart, wholeUrl) {
4283
+ return newUrlPart;
4284
+ }
4285
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: DefaultUrlHandlingStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4286
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: DefaultUrlHandlingStrategy, providedIn: 'root' }); }
4287
+ }
4288
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: DefaultUrlHandlingStrategy, decorators: [{
4289
+ type: Injectable,
4290
+ args: [{ providedIn: 'root' }]
4291
+ }] });
4292
+
4177
4293
  class NavigationTransitions {
4178
4294
  get hasRequestedNavigation() {
4179
4295
  return this.navigationId !== 0;
@@ -4197,6 +4313,10 @@ class NavigationTransitions {
4197
4313
  this.urlSerializer = inject(UrlSerializer);
4198
4314
  this.rootContexts = inject(ChildrenOutletContexts);
4199
4315
  this.inputBindingEnabled = inject(INPUT_BINDER, { optional: true }) !== null;
4316
+ this.titleStrategy = inject(TitleStrategy);
4317
+ this.options = inject(ROUTER_CONFIGURATION, { optional: true }) || {};
4318
+ this.paramsInheritanceStrategy = this.options.paramsInheritanceStrategy || 'emptyOnly';
4319
+ this.urlHandlingStrategy = inject(UrlHandlingStrategy);
4200
4320
  this.navigationId = 0;
4201
4321
  /**
4202
4322
  * Hook that enables you to pause navigation after the preactivation phase.
@@ -4225,8 +4345,8 @@ class NavigationTransitions {
4225
4345
  currentUrlTree: initialUrlTree,
4226
4346
  currentRawUrl: initialUrlTree,
4227
4347
  currentBrowserUrl: initialUrlTree,
4228
- extractedUrl: router.urlHandlingStrategy.extract(initialUrlTree),
4229
- urlAfterRedirects: router.urlHandlingStrategy.extract(initialUrlTree),
4348
+ extractedUrl: this.urlHandlingStrategy.extract(initialUrlTree),
4349
+ urlAfterRedirects: this.urlHandlingStrategy.extract(initialUrlTree),
4230
4350
  rawUrl: initialUrlTree,
4231
4351
  extras: {},
4232
4352
  resolve: null,
@@ -4243,7 +4363,7 @@ class NavigationTransitions {
4243
4363
  });
4244
4364
  return this.transitions.pipe(filter(t => t.id !== 0),
4245
4365
  // Extract URL
4246
- map(t => ({ ...t, extractedUrl: router.urlHandlingStrategy.extract(t.rawUrl) })),
4366
+ map(t => ({ ...t, extractedUrl: this.urlHandlingStrategy.extract(t.rawUrl) })),
4247
4367
  // Using switchMap so we cancel executing navigations when a new one comes in
4248
4368
  switchMap(overallTransitionState => {
4249
4369
  this.currentTransition = overallTransitionState;
@@ -4282,7 +4402,7 @@ class NavigationTransitions {
4282
4402
  t.resolve(null);
4283
4403
  return EMPTY;
4284
4404
  }
4285
- if (router.urlHandlingStrategy.shouldProcessUrl(t.rawUrl)) {
4405
+ if (this.urlHandlingStrategy.shouldProcessUrl(t.rawUrl)) {
4286
4406
  return of(t).pipe(
4287
4407
  // Fire NavigationStart event
4288
4408
  switchMap(t => {
@@ -4296,7 +4416,7 @@ class NavigationTransitions {
4296
4416
  return Promise.resolve(t);
4297
4417
  }),
4298
4418
  // Recognize
4299
- recognize(this.environmentInjector, this.configLoader, this.rootComponentType, router.config, this.urlSerializer, router.paramsInheritanceStrategy),
4419
+ recognize(this.environmentInjector, this.configLoader, this.rootComponentType, router.config, this.urlSerializer, this.paramsInheritanceStrategy),
4300
4420
  // Update URL if in `eager` update mode
4301
4421
  tap(t => {
4302
4422
  overallTransitionState.targetSnapshot = t.targetSnapshot;
@@ -4311,7 +4431,7 @@ class NavigationTransitions {
4311
4431
  }));
4312
4432
  }
4313
4433
  else if (urlTransition &&
4314
- router.urlHandlingStrategy.shouldProcessUrl(t.currentRawUrl)) {
4434
+ this.urlHandlingStrategy.shouldProcessUrl(t.currentRawUrl)) {
4315
4435
  /* When the current URL shouldn't be processed, but the previous one
4316
4436
  * was, we handle this "error condition" by navigating to the
4317
4437
  * previously successful URL, but leaving the URL intact.*/
@@ -4325,6 +4445,7 @@ class NavigationTransitions {
4325
4445
  urlAfterRedirects: extractedUrl,
4326
4446
  extras: { ...extras, skipLocationChange: false, replaceUrl: false },
4327
4447
  };
4448
+ this.currentNavigation.finalUrl = extractedUrl;
4328
4449
  return of(overallTransitionState);
4329
4450
  }
4330
4451
  else {
@@ -4374,7 +4495,7 @@ class NavigationTransitions {
4374
4495
  this.events.next(resolveStart);
4375
4496
  }), switchMap(t => {
4376
4497
  let dataResolved = false;
4377
- return of(t).pipe(resolveData(router.paramsInheritanceStrategy, this.environmentInjector), tap({
4498
+ return of(t).pipe(resolveData(this.paramsInheritanceStrategy, this.environmentInjector), tap({
4378
4499
  next: () => dataResolved = true,
4379
4500
  complete: () => {
4380
4501
  if (!dataResolved) {
@@ -4413,6 +4534,7 @@ class NavigationTransitions {
4413
4534
  const targetRouterState = createRouterState(router.routeReuseStrategy, t.targetSnapshot, t.currentRouterState);
4414
4535
  this.currentTransition =
4415
4536
  overallTransitionState = { ...t, targetRouterState };
4537
+ this.currentNavigation.targetRouterState = targetRouterState;
4416
4538
  return overallTransitionState;
4417
4539
  }), tap(() => {
4418
4540
  this.events.next(new BeforeActivateRoutes());
@@ -4425,7 +4547,7 @@ class NavigationTransitions {
4425
4547
  completed = true;
4426
4548
  this.lastSuccessfulNavigation = this.currentNavigation;
4427
4549
  this.events.next(new NavigationEnd(t.id, this.urlSerializer.serialize(t.extractedUrl), this.urlSerializer.serialize(t.urlAfterRedirects)));
4428
- router.titleStrategy?.updateTitle(t.targetRouterState.snapshot);
4550
+ this.titleStrategy?.updateTitle(t.targetRouterState.snapshot);
4429
4551
  t.resolve(true);
4430
4552
  },
4431
4553
  complete: () => {
@@ -4496,10 +4618,10 @@ class NavigationTransitions {
4496
4618
  this.events.next(navCancel);
4497
4619
  t.resolve(false);
4498
4620
  }
4499
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: NavigationTransitions, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4500
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: NavigationTransitions, providedIn: 'root' }); }
4621
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: NavigationTransitions, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4622
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: NavigationTransitions, providedIn: 'root' }); }
4501
4623
  }
4502
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: NavigationTransitions, decorators: [{
4624
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: NavigationTransitions, decorators: [{
4503
4625
  type: Injectable,
4504
4626
  args: [{ providedIn: 'root' }]
4505
4627
  }], ctorParameters: function () { return []; } });
@@ -4507,83 +4629,6 @@ function isBrowserTriggeredNavigation(source) {
4507
4629
  return source !== IMPERATIVE_NAVIGATION;
4508
4630
  }
4509
4631
 
4510
- /**
4511
- * Provides a strategy for setting the page title after a router navigation.
4512
- *
4513
- * The built-in implementation traverses the router state snapshot and finds the deepest primary
4514
- * outlet with `title` property. Given the `Routes` below, navigating to
4515
- * `/base/child(popup:aux)` would result in the document title being set to "child".
4516
- * ```
4517
- * [
4518
- * {path: 'base', title: 'base', children: [
4519
- * {path: 'child', title: 'child'},
4520
- * ],
4521
- * {path: 'aux', outlet: 'popup', title: 'popupTitle'}
4522
- * ]
4523
- * ```
4524
- *
4525
- * This class can be used as a base class for custom title strategies. That is, you can create your
4526
- * own class that extends the `TitleStrategy`. Note that in the above example, the `title`
4527
- * from the named outlet is never used. However, a custom strategy might be implemented to
4528
- * incorporate titles in named outlets.
4529
- *
4530
- * @publicApi
4531
- * @see [Page title guide](guide/router#setting-the-page-title)
4532
- */
4533
- class TitleStrategy {
4534
- /**
4535
- * @returns The `title` of the deepest primary route.
4536
- */
4537
- buildTitle(snapshot) {
4538
- let pageTitle;
4539
- let route = snapshot.root;
4540
- while (route !== undefined) {
4541
- pageTitle = this.getResolvedTitleForRoute(route) ?? pageTitle;
4542
- route = route.children.find(child => child.outlet === PRIMARY_OUTLET);
4543
- }
4544
- return pageTitle;
4545
- }
4546
- /**
4547
- * Given an `ActivatedRouteSnapshot`, returns the final value of the
4548
- * `Route.title` property, which can either be a static string or a resolved value.
4549
- */
4550
- getResolvedTitleForRoute(snapshot) {
4551
- return snapshot.data[RouteTitleKey];
4552
- }
4553
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: TitleStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4554
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: TitleStrategy, providedIn: 'root', useFactory: () => inject(DefaultTitleStrategy) }); }
4555
- }
4556
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: TitleStrategy, decorators: [{
4557
- type: Injectable,
4558
- args: [{ providedIn: 'root', useFactory: () => inject(DefaultTitleStrategy) }]
4559
- }] });
4560
- /**
4561
- * The default `TitleStrategy` used by the router that updates the title using the `Title` service.
4562
- */
4563
- class DefaultTitleStrategy extends TitleStrategy {
4564
- constructor(title) {
4565
- super();
4566
- this.title = title;
4567
- }
4568
- /**
4569
- * Sets the title of the browser to the given value.
4570
- *
4571
- * @param title The `pageTitle` from the deepest primary route.
4572
- */
4573
- updateTitle(snapshot) {
4574
- const title = this.buildTitle(snapshot);
4575
- if (title !== undefined) {
4576
- this.title.setTitle(title);
4577
- }
4578
- }
4579
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: DefaultTitleStrategy, deps: [{ token: i1.Title }], target: i0.ɵɵFactoryTarget.Injectable }); }
4580
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: DefaultTitleStrategy, providedIn: 'root' }); }
4581
- }
4582
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: DefaultTitleStrategy, decorators: [{
4583
- type: Injectable,
4584
- args: [{ providedIn: 'root' }]
4585
- }], ctorParameters: function () { return [{ type: i1.Title }]; } });
4586
-
4587
4632
  /**
4588
4633
  * @description
4589
4634
  *
@@ -4592,10 +4637,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.1",
4592
4637
  * @publicApi
4593
4638
  */
4594
4639
  class RouteReuseStrategy {
4595
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: RouteReuseStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4596
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: RouteReuseStrategy, providedIn: 'root', useFactory: () => inject(DefaultRouteReuseStrategy) }); }
4640
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: RouteReuseStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4641
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: RouteReuseStrategy, providedIn: 'root', useFactory: () => inject(DefaultRouteReuseStrategy) }); }
4597
4642
  }
4598
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: RouteReuseStrategy, decorators: [{
4643
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: RouteReuseStrategy, decorators: [{
4599
4644
  type: Injectable,
4600
4645
  args: [{ providedIn: 'root', useFactory: () => inject(DefaultRouteReuseStrategy) }]
4601
4646
  }] });
@@ -4646,61 +4691,243 @@ class BaseRouteReuseStrategy {
4646
4691
  }
4647
4692
  }
4648
4693
  class DefaultRouteReuseStrategy extends BaseRouteReuseStrategy {
4649
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: DefaultRouteReuseStrategy, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
4650
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: DefaultRouteReuseStrategy, providedIn: 'root' }); }
4651
- }
4652
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: DefaultRouteReuseStrategy, decorators: [{
4653
- type: Injectable,
4654
- args: [{ providedIn: 'root' }]
4655
- }] });
4656
-
4657
- /**
4658
- * A [DI token](guide/glossary/#di-token) for the router service.
4659
- *
4660
- * @publicApi
4661
- */
4662
- const ROUTER_CONFIGURATION = new InjectionToken((typeof ngDevMode === 'undefined' || ngDevMode) ? 'router config' : '', {
4663
- providedIn: 'root',
4664
- factory: () => ({}),
4665
- });
4666
-
4667
- /**
4668
- * @description
4669
- *
4670
- * Provides a way to migrate AngularJS applications to Angular.
4671
- *
4672
- * @publicApi
4673
- */
4674
- class UrlHandlingStrategy {
4675
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: UrlHandlingStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4676
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: UrlHandlingStrategy, providedIn: 'root', useFactory: () => inject(DefaultUrlHandlingStrategy) }); }
4677
- }
4678
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: UrlHandlingStrategy, decorators: [{
4679
- type: Injectable,
4680
- args: [{ providedIn: 'root', useFactory: () => inject(DefaultUrlHandlingStrategy) }]
4681
- }] });
4682
- /**
4683
- * @publicApi
4684
- */
4685
- class DefaultUrlHandlingStrategy {
4686
- shouldProcessUrl(url) {
4687
- return true;
4688
- }
4689
- extract(url) {
4690
- return url;
4691
- }
4692
- merge(newUrlPart, wholeUrl) {
4693
- return newUrlPart;
4694
- }
4695
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: DefaultUrlHandlingStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4696
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: DefaultUrlHandlingStrategy, providedIn: 'root' }); }
4694
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: DefaultRouteReuseStrategy, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
4695
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: DefaultRouteReuseStrategy, providedIn: 'root' }); }
4697
4696
  }
4698
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: DefaultUrlHandlingStrategy, decorators: [{
4697
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: DefaultRouteReuseStrategy, decorators: [{
4699
4698
  type: Injectable,
4700
4699
  args: [{ providedIn: 'root' }]
4701
4700
  }] });
4702
4701
 
4703
- var NavigationResult;
4702
+ class StateManager {
4703
+ constructor() {
4704
+ this.location = inject(Location);
4705
+ this.urlSerializer = inject(UrlSerializer);
4706
+ this.options = inject(ROUTER_CONFIGURATION, { optional: true }) || {};
4707
+ this.canceledNavigationResolution = this.options.canceledNavigationResolution || 'replace';
4708
+ // These are currently writable via the Router public API but are deprecated and should be made
4709
+ // `private readonly` in the future.
4710
+ this.urlHandlingStrategy = inject(UrlHandlingStrategy);
4711
+ this.urlUpdateStrategy = this.options.urlUpdateStrategy || 'deferred';
4712
+ /**
4713
+ * Represents the activated `UrlTree` that the `Router` is configured to handle (through
4714
+ * `UrlHandlingStrategy`). That is, after we find the route config tree that we're going to
4715
+ * activate, run guards, and are just about to activate the route, we set the currentUrlTree.
4716
+ *
4717
+ * This should match the `browserUrlTree` when a navigation succeeds. If the
4718
+ * `UrlHandlingStrategy.shouldProcessUrl` is `false`, only the `browserUrlTree` is updated.
4719
+ * @internal
4720
+ */
4721
+ this.currentUrlTree = new UrlTree();
4722
+ /**
4723
+ * Meant to represent the entire browser url after a successful navigation. In the life of a
4724
+ * navigation transition:
4725
+ * 1. The rawUrl represents the full URL that's being navigated to
4726
+ * 2. We apply redirects, which might only apply to _part_ of the URL (due to
4727
+ * `UrlHandlingStrategy`).
4728
+ * 3. Right before activation (because we assume activation will succeed), we update the
4729
+ * rawUrlTree to be a combination of the urlAfterRedirects (again, this might only apply to part
4730
+ * of the initial url) and the rawUrl of the transition (which was the original navigation url in
4731
+ * its full form).
4732
+ * @internal
4733
+ *
4734
+ * Note that this is _only_ here to support `UrlHandlingStrategy.extract` and
4735
+ * `UrlHandlingStrategy.shouldProcessUrl`. If those didn't exist, we could get by with
4736
+ * `currentUrlTree` alone. If a new Router were to be provided (i.e. one that works with the
4737
+ * browser navigation API), we should think about whether this complexity should be carried over.
4738
+ *
4739
+ * - extract: `rawUrlTree` is needed because `extract` may only return part
4740
+ * of the navigation URL. Thus, `currentUrlTree` may only represent _part_ of the browser URL.
4741
+ * When a navigation gets cancelled and we need to reset the URL or a new navigation occurs, we
4742
+ * need to know the _whole_ browser URL, not just the part handled by UrlHandlingStrategy.
4743
+ * - shouldProcessUrl: When this returns `false`, the router just ignores the navigation but still
4744
+ * updates the `rawUrlTree` with the assumption that the navigation was caused by the location
4745
+ * change listener due to a URL update by the AngularJS router. In this case, we still need to
4746
+ * know what the browser's URL is for future navigations.
4747
+ *
4748
+ */
4749
+ this.rawUrlTree = this.currentUrlTree;
4750
+ /**
4751
+ * Meant to represent the part of the browser url that the `Router` is set up to handle (via the
4752
+ * `UrlHandlingStrategy`). This value is updated immediately after the browser url is updated (or
4753
+ * the browser url update is skipped via `skipLocationChange`). With that, note that
4754
+ * `browserUrlTree` _may not_ reflect the actual browser URL for two reasons:
4755
+ *
4756
+ * 1. `UrlHandlingStrategy` only handles part of the URL
4757
+ * 2. `skipLocationChange` does not update the browser url.
4758
+ *
4759
+ * So to reiterate, `browserUrlTree` only represents the Router's internal understanding of the
4760
+ * current route, either before guards with `urlUpdateStrategy === 'eager'` or right before
4761
+ * activation with `'deferred'`.
4762
+ *
4763
+ * This should match the `currentUrlTree` when the navigation succeeds.
4764
+ * @internal
4765
+ */
4766
+ this.browserUrlTree = this.currentUrlTree;
4767
+ /**
4768
+ * The id of the currently active page in the router.
4769
+ * Updated to the transition's target id on a successful navigation.
4770
+ *
4771
+ * This is used to track what page the router last activated. When an attempted navigation fails,
4772
+ * the router can then use this to compute how to restore the state back to the previously active
4773
+ * page.
4774
+ */
4775
+ this.currentPageId = 0;
4776
+ this.lastSuccessfulId = -1;
4777
+ this.routerState = createEmptyState(this.currentUrlTree, null);
4778
+ this.stateMemento = this.createStateMemento();
4779
+ }
4780
+ /**
4781
+ * The ɵrouterPageId of whatever page is currently active in the browser history. This is
4782
+ * important for computing the target page id for new navigations because we need to ensure each
4783
+ * page id in the browser history is 1 more than the previous entry.
4784
+ */
4785
+ get browserPageId() {
4786
+ if (this.canceledNavigationResolution !== 'computed') {
4787
+ return this.currentPageId;
4788
+ }
4789
+ return this.location.getState()?.ɵrouterPageId ?? this.currentPageId;
4790
+ }
4791
+ createStateMemento() {
4792
+ return {
4793
+ rawUrlTree: this.rawUrlTree,
4794
+ browserUrlTree: this.browserUrlTree,
4795
+ currentUrlTree: this.currentUrlTree,
4796
+ routerState: this.routerState,
4797
+ };
4798
+ }
4799
+ handleNavigationEvent(e, currentTransition) {
4800
+ if (e instanceof NavigationStart) {
4801
+ this.stateMemento = this.createStateMemento();
4802
+ // If the source of the navigation is from a browser event, the URL is
4803
+ // already updated. We already need to sync the internal state.
4804
+ if (isBrowserTriggeredNavigation(currentTransition.trigger)) {
4805
+ this.browserUrlTree = currentTransition.extractedUrl;
4806
+ }
4807
+ }
4808
+ else if (e instanceof NavigationSkipped) {
4809
+ this.rawUrlTree = currentTransition.initialUrl;
4810
+ }
4811
+ else if (e instanceof RoutesRecognized) {
4812
+ if (this.urlUpdateStrategy === 'eager') {
4813
+ if (!currentTransition.extras.skipLocationChange) {
4814
+ const rawUrl = this.urlHandlingStrategy.merge(currentTransition.finalUrl, currentTransition.initialUrl);
4815
+ this.setBrowserUrl(rawUrl, currentTransition);
4816
+ }
4817
+ this.browserUrlTree = currentTransition.finalUrl;
4818
+ }
4819
+ }
4820
+ else if (e instanceof BeforeActivateRoutes) {
4821
+ this.currentUrlTree = currentTransition.finalUrl;
4822
+ this.rawUrlTree =
4823
+ this.urlHandlingStrategy.merge(currentTransition.finalUrl, currentTransition.initialUrl);
4824
+ this.routerState = currentTransition.targetRouterState;
4825
+ if (this.urlUpdateStrategy === 'deferred') {
4826
+ if (!currentTransition.extras.skipLocationChange) {
4827
+ this.setBrowserUrl(this.rawUrlTree, currentTransition);
4828
+ }
4829
+ this.browserUrlTree = currentTransition.finalUrl;
4830
+ }
4831
+ }
4832
+ else if (e instanceof NavigationCancel &&
4833
+ (e.code === 3 /* NavigationCancellationCode.GuardRejected */ ||
4834
+ e.code === 2 /* NavigationCancellationCode.NoDataFromResolver */)) {
4835
+ this.restoreHistory(currentTransition);
4836
+ }
4837
+ else if (e instanceof NavigationError) {
4838
+ this.restoreHistory(currentTransition, true);
4839
+ }
4840
+ else if (e instanceof NavigationEnd) {
4841
+ this.lastSuccessfulId = e.id;
4842
+ this.currentPageId = this.browserPageId;
4843
+ }
4844
+ }
4845
+ setBrowserUrl(url, transition) {
4846
+ const path = this.urlSerializer.serialize(url);
4847
+ if (this.location.isCurrentPathEqualTo(path) || !!transition.extras.replaceUrl) {
4848
+ // replacements do not update the target page
4849
+ const currentBrowserPageId = this.browserPageId;
4850
+ const state = {
4851
+ ...transition.extras.state,
4852
+ ...this.generateNgRouterState(transition.id, currentBrowserPageId)
4853
+ };
4854
+ this.location.replaceState(path, '', state);
4855
+ }
4856
+ else {
4857
+ const state = {
4858
+ ...transition.extras.state,
4859
+ ...this.generateNgRouterState(transition.id, this.browserPageId + 1)
4860
+ };
4861
+ this.location.go(path, '', state);
4862
+ }
4863
+ }
4864
+ /**
4865
+ * Performs the necessary rollback action to restore the browser URL to the
4866
+ * state before the transition.
4867
+ * @internal
4868
+ */
4869
+ restoreHistory(navigation, restoringFromCaughtError = false) {
4870
+ if (this.canceledNavigationResolution === 'computed') {
4871
+ const currentBrowserPageId = this.browserPageId;
4872
+ const targetPagePosition = this.currentPageId - currentBrowserPageId;
4873
+ if (targetPagePosition !== 0) {
4874
+ this.location.historyGo(targetPagePosition);
4875
+ }
4876
+ else if (this.currentUrlTree === navigation.finalUrl && targetPagePosition === 0) {
4877
+ // We got to the activation stage (where currentUrlTree is set to the navigation's
4878
+ // finalUrl), but we weren't moving anywhere in history (skipLocationChange or replaceUrl).
4879
+ // We still need to reset the router state back to what it was when the navigation started.
4880
+ this.resetState(navigation);
4881
+ // TODO(atscott): resetting the `browserUrlTree` should really be done in `resetState`.
4882
+ // Investigate if this can be done by running TGP.
4883
+ this.browserUrlTree = this.stateMemento.browserUrlTree;
4884
+ this.resetUrlToCurrentUrlTree();
4885
+ }
4886
+ else {
4887
+ // The browser URL and router state was not updated before the navigation cancelled so
4888
+ // there's no restoration needed.
4889
+ }
4890
+ }
4891
+ else if (this.canceledNavigationResolution === 'replace') {
4892
+ // TODO(atscott): It seems like we should _always_ reset the state here. It would be a no-op
4893
+ // for `deferred` navigations that haven't change the internal state yet because guards
4894
+ // reject. For 'eager' navigations, it seems like we also really should reset the state
4895
+ // because the navigation was cancelled. Investigate if this can be done by running TGP.
4896
+ if (restoringFromCaughtError) {
4897
+ this.resetState(navigation);
4898
+ }
4899
+ this.resetUrlToCurrentUrlTree();
4900
+ }
4901
+ }
4902
+ resetState(navigation) {
4903
+ this.routerState = this.stateMemento.routerState;
4904
+ this.currentUrlTree = this.stateMemento.currentUrlTree;
4905
+ // Note here that we use the urlHandlingStrategy to get the reset `rawUrlTree` because it may be
4906
+ // configured to handle only part of the navigation URL. This means we would only want to reset
4907
+ // the part of the navigation handled by the Angular router rather than the whole URL. In
4908
+ // addition, the URLHandlingStrategy may be configured to specifically preserve parts of the URL
4909
+ // when merging, such as the query params so they are not lost on a refresh.
4910
+ this.rawUrlTree =
4911
+ this.urlHandlingStrategy.merge(this.currentUrlTree, navigation.finalUrl ?? this.rawUrlTree);
4912
+ }
4913
+ resetUrlToCurrentUrlTree() {
4914
+ this.location.replaceState(this.urlSerializer.serialize(this.rawUrlTree), '', this.generateNgRouterState(this.lastSuccessfulId, this.currentPageId));
4915
+ }
4916
+ generateNgRouterState(navigationId, routerPageId) {
4917
+ if (this.canceledNavigationResolution === 'computed') {
4918
+ return { navigationId, ɵrouterPageId: routerPageId };
4919
+ }
4920
+ return { navigationId };
4921
+ }
4922
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: StateManager, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4923
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: StateManager, providedIn: 'root' }); }
4924
+ }
4925
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: StateManager, decorators: [{
4926
+ type: Injectable,
4927
+ args: [{ providedIn: 'root' }]
4928
+ }] });
4929
+
4930
+ var NavigationResult;
4704
4931
  (function (NavigationResult) {
4705
4932
  NavigationResult[NavigationResult["COMPLETE"] = 0] = "COMPLETE";
4706
4933
  NavigationResult[NavigationResult["FAILED"] = 1] = "FAILED";
@@ -4772,21 +4999,14 @@ const subsetMatchOptions = {
4772
4999
  * @publicApi
4773
5000
  */
4774
5001
  class Router {
4775
- // TODO(b/260747083): This should not exist and navigationId should be private in
4776
- // `NavigationTransitions`
4777
- get navigationId() {
4778
- return this.navigationTransitions.navigationId;
5002
+ get currentUrlTree() {
5003
+ return this.stateManager.currentUrlTree;
4779
5004
  }
4780
- /**
4781
- * The ɵrouterPageId of whatever page is currently active in the browser history. This is
4782
- * important for computing the target page id for new navigations because we need to ensure each
4783
- * page id in the browser history is 1 more than the previous entry.
4784
- */
4785
- get browserPageId() {
4786
- if (this.canceledNavigationResolution !== 'computed') {
4787
- return this.currentPageId;
4788
- }
4789
- return this.location.getState()?.ɵrouterPageId ?? this.currentPageId;
5005
+ get rawUrlTree() {
5006
+ return this.stateManager.rawUrlTree;
5007
+ }
5008
+ get browserUrlTree() {
5009
+ return this.stateManager.browserUrlTree;
4790
5010
  }
4791
5011
  /**
4792
5012
  * An event stream for routing events.
@@ -4798,27 +5018,30 @@ class Router {
4798
5018
  // the change.
4799
5019
  return this._events;
4800
5020
  }
5021
+ /**
5022
+ * The current state of routing in this NgModule.
5023
+ */
5024
+ get routerState() {
5025
+ return this.stateManager.routerState;
5026
+ }
4801
5027
  constructor() {
4802
5028
  this.disposed = false;
4803
- /**
4804
- * The id of the currently active page in the router.
4805
- * Updated to the transition's target id on a successful navigation.
4806
- *
4807
- * This is used to track what page the router last activated. When an attempted navigation fails,
4808
- * the router can then use this to compute how to restore the state back to the previously active
4809
- * page.
4810
- */
4811
- this.currentPageId = 0;
4812
- this.console = inject(ɵConsole);
4813
5029
  this.isNgZoneEnabled = false;
5030
+ this.console = inject(ɵConsole);
5031
+ this.stateManager = inject(StateManager);
5032
+ this.options = inject(ROUTER_CONFIGURATION, { optional: true }) || {};
5033
+ this.pendingTasks = inject(ɵInitialRenderPendingTasks);
5034
+ this.urlUpdateStrategy = this.options.urlUpdateStrategy || 'deferred';
5035
+ this.navigationTransitions = inject(NavigationTransitions);
5036
+ this.urlSerializer = inject(UrlSerializer);
5037
+ this.location = inject(Location);
5038
+ this.urlHandlingStrategy = inject(UrlHandlingStrategy);
4814
5039
  /**
4815
5040
  * The private `Subject` type for the public events exposed in the getter. This is used internally
4816
5041
  * to push events to. The separate field allows us to expose separate types in the public API
4817
5042
  * (i.e., an Observable rather than the Subject).
4818
5043
  */
4819
5044
  this._events = new Subject();
4820
- this.options = inject(ROUTER_CONFIGURATION, { optional: true }) || {};
4821
- this.pendingTasks = inject(ɵInitialRenderPendingTasks);
4822
5045
  /**
4823
5046
  * A handler for navigation errors in this NgModule.
4824
5047
  *
@@ -4833,8 +5056,6 @@ class Router {
4833
5056
  * The most common case is a `%` sign
4834
5057
  * that's not encoded and is not part of a percent encoded sequence.
4835
5058
  *
4836
- * @deprecated URI parsing errors should be handled in the `UrlSerializer`.
4837
- *
4838
5059
  * @see {@link RouterModule}
4839
5060
  */
4840
5061
  this.malformedUriErrorHandler = this.options.malformedUriErrorHandler || defaultMalformedUriErrorHandler;
@@ -4843,15 +5064,6 @@ class Router {
4843
5064
  * false otherwise.
4844
5065
  */
4845
5066
  this.navigated = false;
4846
- this.lastSuccessfulId = -1;
4847
- /**
4848
- * A strategy for extracting and merging URLs.
4849
- * Used for AngularJS to Angular migrations.
4850
- *
4851
- * @deprecated Configure using `providers` instead:
4852
- * `{provide: UrlHandlingStrategy, useClass: MyStrategy}`.
4853
- */
4854
- this.urlHandlingStrategy = inject(UrlHandlingStrategy);
4855
5067
  /**
4856
5068
  * A strategy for re-using routes.
4857
5069
  *
@@ -4859,13 +5071,6 @@ class Router {
4859
5071
  * `{provide: RouteReuseStrategy, useClass: MyStrategy}`.
4860
5072
  */
4861
5073
  this.routeReuseStrategy = inject(RouteReuseStrategy);
4862
- /**
4863
- * A strategy for setting the title based on the `routerState`.
4864
- *
4865
- * @deprecated Configure using `providers` instead:
4866
- * `{provide: TitleStrategy, useClass: MyStrategy}`.
4867
- */
4868
- this.titleStrategy = inject(TitleStrategy);
4869
5074
  /**
4870
5075
  * How to handle a navigation request to the current URL.
4871
5076
  *
@@ -4876,65 +5081,7 @@ class Router {
4876
5081
  * @see {@link RouterModule}
4877
5082
  */
4878
5083
  this.onSameUrlNavigation = this.options.onSameUrlNavigation || 'ignore';
4879
- /**
4880
- * How to merge parameters, data, resolved data, and title from parent to child
4881
- * routes. One of:
4882
- *
4883
- * - `'emptyOnly'` : Inherit parent parameters, data, and resolved data
4884
- * for path-less or component-less routes.
4885
- * - `'always'` : Inherit parent parameters, data, and resolved data
4886
- * for all child routes.
4887
- *
4888
- * @deprecated Configure this through `provideRouter` or `RouterModule.forRoot` instead.
4889
- * @see {@link withRouterConfig}
4890
- * @see {@link provideRouter}
4891
- * @see {@link RouterModule}
4892
- */
4893
- this.paramsInheritanceStrategy = this.options.paramsInheritanceStrategy || 'emptyOnly';
4894
- /**
4895
- * Determines when the router updates the browser URL.
4896
- * By default (`"deferred"`), updates the browser URL after navigation has finished.
4897
- * Set to `'eager'` to update the browser URL at the beginning of navigation.
4898
- * You can choose to update early so that, if navigation fails,
4899
- * you can show an error message with the URL that failed.
4900
- *
4901
- * @deprecated Configure this through `provideRouter` or `RouterModule.forRoot` instead.
4902
- * @see {@link withRouterConfig}
4903
- * @see {@link provideRouter}
4904
- * @see {@link RouterModule}
4905
- */
4906
- this.urlUpdateStrategy = this.options.urlUpdateStrategy || 'deferred';
4907
- /**
4908
- * Configures how the Router attempts to restore state when a navigation is cancelled.
4909
- *
4910
- * 'replace' - Always uses `location.replaceState` to set the browser state to the state of the
4911
- * router before the navigation started. This means that if the URL of the browser is updated
4912
- * _before_ the navigation is canceled, the Router will simply replace the item in history rather
4913
- * than trying to restore to the previous location in the session history. This happens most
4914
- * frequently with `urlUpdateStrategy: 'eager'` and navigations with the browser back/forward
4915
- * buttons.
4916
- *
4917
- * 'computed' - Will attempt to return to the same index in the session history that corresponds
4918
- * to the Angular route when the navigation gets cancelled. For example, if the browser back
4919
- * button is clicked and the navigation is cancelled, the Router will trigger a forward navigation
4920
- * and vice versa.
4921
- *
4922
- * Note: the 'computed' option is incompatible with any `UrlHandlingStrategy` which only
4923
- * handles a portion of the URL because the history restoration navigates to the previous place in
4924
- * the browser history rather than simply resetting a portion of the URL.
4925
- *
4926
- * The default value is `replace`.
4927
- *
4928
- * @deprecated Configure this through `provideRouter` or `RouterModule.forRoot` instead.
4929
- * @see {@link withRouterConfig}
4930
- * @see {@link provideRouter}
4931
- * @see {@link RouterModule}
4932
- */
4933
- this.canceledNavigationResolution = this.options.canceledNavigationResolution || 'replace';
4934
5084
  this.config = inject(ROUTES, { optional: true })?.flat() ?? [];
4935
- this.navigationTransitions = inject(NavigationTransitions);
4936
- this.urlSerializer = inject(UrlSerializer);
4937
- this.location = inject(Location);
4938
5085
  /**
4939
5086
  * Indicates whether the application has opted in to binding Router data to component inputs.
4940
5087
  *
@@ -4945,94 +5092,48 @@ class Router {
4945
5092
  this.eventsSubscription = new Subscription();
4946
5093
  this.isNgZoneEnabled = inject(NgZone) instanceof NgZone && NgZone.isInAngularZone();
4947
5094
  this.resetConfig(this.config);
4948
- this.currentUrlTree = new UrlTree();
4949
- this.rawUrlTree = this.currentUrlTree;
4950
- this.browserUrlTree = this.currentUrlTree;
4951
- this.routerState = createEmptyState(this.currentUrlTree, null);
4952
5095
  this.navigationTransitions.setupNavigations(this, this.currentUrlTree, this.routerState)
4953
- .subscribe(t => {
4954
- this.lastSuccessfulId = t.id;
4955
- this.currentPageId = this.browserPageId;
4956
- }, e => {
4957
- this.console.warn(`Unhandled Navigation Error: ${e}`);
5096
+ .subscribe({
5097
+ error: (e) => {
5098
+ this.console.warn(ngDevMode ? `Unhandled Navigation Error: ${e}` : e);
5099
+ }
4958
5100
  });
4959
5101
  this.subscribeToNavigationEvents();
4960
5102
  }
4961
5103
  subscribeToNavigationEvents() {
4962
5104
  const subscription = this.navigationTransitions.events.subscribe(e => {
4963
5105
  try {
4964
- const { currentTransition } = this.navigationTransitions;
4965
- if (currentTransition === null) {
4966
- if (isPublicRouterEvent(e)) {
4967
- this._events.next(e);
4968
- }
4969
- return;
4970
- }
4971
- if (e instanceof NavigationStart) {
4972
- // If the source of the navigation is from a browser event, the URL is
4973
- // already updated. We already need to sync the internal state.
4974
- if (isBrowserTriggeredNavigation(currentTransition.source)) {
4975
- this.browserUrlTree = currentTransition.extractedUrl;
4976
- }
4977
- }
4978
- else if (e instanceof NavigationSkipped) {
4979
- this.rawUrlTree = currentTransition.rawUrl;
4980
- }
4981
- else if (e instanceof RoutesRecognized) {
4982
- if (this.urlUpdateStrategy === 'eager') {
4983
- if (!currentTransition.extras.skipLocationChange) {
4984
- const rawUrl = this.urlHandlingStrategy.merge(currentTransition.urlAfterRedirects, currentTransition.rawUrl);
4985
- this.setBrowserUrl(rawUrl, currentTransition);
4986
- }
4987
- this.browserUrlTree = currentTransition.urlAfterRedirects;
4988
- }
4989
- }
4990
- else if (e instanceof BeforeActivateRoutes) {
4991
- this.currentUrlTree = currentTransition.urlAfterRedirects;
4992
- this.rawUrlTree = this.urlHandlingStrategy.merge(currentTransition.urlAfterRedirects, currentTransition.rawUrl);
4993
- this.routerState = currentTransition.targetRouterState;
4994
- if (this.urlUpdateStrategy === 'deferred') {
4995
- if (!currentTransition.extras.skipLocationChange) {
4996
- this.setBrowserUrl(this.rawUrlTree, currentTransition);
4997
- }
4998
- this.browserUrlTree = currentTransition.urlAfterRedirects;
4999
- }
5000
- }
5001
- else if (e instanceof NavigationCancel) {
5002
- if (e.code !== 0 /* NavigationCancellationCode.Redirect */ &&
5106
+ const currentTransition = this.navigationTransitions.currentTransition;
5107
+ const currentNavigation = this.navigationTransitions.currentNavigation;
5108
+ if (currentTransition !== null && currentNavigation !== null) {
5109
+ this.stateManager.handleNavigationEvent(e, currentNavigation);
5110
+ if (e instanceof NavigationCancel && e.code !== 0 /* NavigationCancellationCode.Redirect */ &&
5003
5111
  e.code !== 1 /* NavigationCancellationCode.SupersededByNewNavigation */) {
5004
5112
  // It seems weird that `navigated` is set to `true` when the navigation is rejected,
5005
5113
  // however it's how things were written initially. Investigation would need to be done
5006
5114
  // to determine if this can be removed.
5007
5115
  this.navigated = true;
5008
5116
  }
5009
- if (e.code === 3 /* NavigationCancellationCode.GuardRejected */ ||
5010
- e.code === 2 /* NavigationCancellationCode.NoDataFromResolver */) {
5011
- this.restoreHistory(currentTransition);
5117
+ else if (e instanceof NavigationEnd) {
5118
+ this.navigated = true;
5119
+ }
5120
+ else if (e instanceof RedirectRequest) {
5121
+ const mergedTree = this.urlHandlingStrategy.merge(e.url, currentTransition.currentRawUrl);
5122
+ const extras = {
5123
+ skipLocationChange: currentTransition.extras.skipLocationChange,
5124
+ // The URL is already updated at this point if we have 'eager' URL
5125
+ // updates or if the navigation was triggered by the browser (back
5126
+ // button, URL bar, etc). We want to replace that item in history
5127
+ // if the navigation is rejected.
5128
+ replaceUrl: this.urlUpdateStrategy === 'eager' ||
5129
+ isBrowserTriggeredNavigation(currentTransition.source)
5130
+ };
5131
+ this.scheduleNavigation(mergedTree, IMPERATIVE_NAVIGATION, null, extras, {
5132
+ resolve: currentTransition.resolve,
5133
+ reject: currentTransition.reject,
5134
+ promise: currentTransition.promise
5135
+ });
5012
5136
  }
5013
- }
5014
- else if (e instanceof RedirectRequest) {
5015
- const mergedTree = this.urlHandlingStrategy.merge(e.url, currentTransition.currentRawUrl);
5016
- const extras = {
5017
- skipLocationChange: currentTransition.extras.skipLocationChange,
5018
- // The URL is already updated at this point if we have 'eager' URL
5019
- // updates or if the navigation was triggered by the browser (back
5020
- // button, URL bar, etc). We want to replace that item in history
5021
- // if the navigation is rejected.
5022
- replaceUrl: this.urlUpdateStrategy === 'eager' ||
5023
- isBrowserTriggeredNavigation(currentTransition.source)
5024
- };
5025
- this.scheduleNavigation(mergedTree, IMPERATIVE_NAVIGATION, null, extras, {
5026
- resolve: currentTransition.resolve,
5027
- reject: currentTransition.reject,
5028
- promise: currentTransition.promise
5029
- });
5030
- }
5031
- if (e instanceof NavigationError) {
5032
- this.restoreHistory(currentTransition, true);
5033
- }
5034
- if (e instanceof NavigationEnd) {
5035
- this.navigated = true;
5036
5137
  }
5037
5138
  // Note that it's important to have the Router process the events _before_ the event is
5038
5139
  // pushed through the public observable. This ensures the correct router state is in place
@@ -5154,7 +5255,6 @@ class Router {
5154
5255
  (typeof ngDevMode === 'undefined' || ngDevMode) && validateConfig(config);
5155
5256
  this.config = config.map(standardizeConfig);
5156
5257
  this.navigated = false;
5157
- this.lastSuccessfulId = -1;
5158
5258
  }
5159
5259
  /** @nodoc */
5160
5260
  ngOnDestroy() {
@@ -5371,7 +5471,6 @@ class Router {
5371
5471
  return result;
5372
5472
  }, {});
5373
5473
  }
5374
- /** @internal */
5375
5474
  scheduleNavigation(rawUrl, source, restoredState, extras, priorPromise) {
5376
5475
  if (this.disposed) {
5377
5476
  return Promise.resolve(false);
@@ -5417,88 +5516,10 @@ class Router {
5417
5516
  return Promise.reject(e);
5418
5517
  });
5419
5518
  }
5420
- /** @internal */
5421
- setBrowserUrl(url, transition) {
5422
- const path = this.urlSerializer.serialize(url);
5423
- if (this.location.isCurrentPathEqualTo(path) || !!transition.extras.replaceUrl) {
5424
- // replacements do not update the target page
5425
- const currentBrowserPageId = this.browserPageId;
5426
- const state = {
5427
- ...transition.extras.state,
5428
- ...this.generateNgRouterState(transition.id, currentBrowserPageId)
5429
- };
5430
- this.location.replaceState(path, '', state);
5431
- }
5432
- else {
5433
- const state = {
5434
- ...transition.extras.state,
5435
- ...this.generateNgRouterState(transition.id, this.browserPageId + 1)
5436
- };
5437
- this.location.go(path, '', state);
5438
- }
5439
- }
5440
- /**
5441
- * Performs the necessary rollback action to restore the browser URL to the
5442
- * state before the transition.
5443
- * @internal
5444
- */
5445
- restoreHistory(transition, restoringFromCaughtError = false) {
5446
- if (this.canceledNavigationResolution === 'computed') {
5447
- const currentBrowserPageId = this.browserPageId;
5448
- const targetPagePosition = this.currentPageId - currentBrowserPageId;
5449
- if (targetPagePosition !== 0) {
5450
- this.location.historyGo(targetPagePosition);
5451
- }
5452
- else if (this.currentUrlTree === this.getCurrentNavigation()?.finalUrl &&
5453
- targetPagePosition === 0) {
5454
- // We got to the activation stage (where currentUrlTree is set to the navigation's
5455
- // finalUrl), but we weren't moving anywhere in history (skipLocationChange or replaceUrl).
5456
- // We still need to reset the router state back to what it was when the navigation started.
5457
- this.resetState(transition);
5458
- // TODO(atscott): resetting the `browserUrlTree` should really be done in `resetState`.
5459
- // Investigate if this can be done by running TGP.
5460
- this.browserUrlTree = transition.currentUrlTree;
5461
- this.resetUrlToCurrentUrlTree();
5462
- }
5463
- else {
5464
- // The browser URL and router state was not updated before the navigation cancelled so
5465
- // there's no restoration needed.
5466
- }
5467
- }
5468
- else if (this.canceledNavigationResolution === 'replace') {
5469
- // TODO(atscott): It seems like we should _always_ reset the state here. It would be a no-op
5470
- // for `deferred` navigations that haven't change the internal state yet because guards
5471
- // reject. For 'eager' navigations, it seems like we also really should reset the state
5472
- // because the navigation was cancelled. Investigate if this can be done by running TGP.
5473
- if (restoringFromCaughtError) {
5474
- this.resetState(transition);
5475
- }
5476
- this.resetUrlToCurrentUrlTree();
5477
- }
5478
- }
5479
- resetState(t) {
5480
- this.routerState = t.currentRouterState;
5481
- this.currentUrlTree = t.currentUrlTree;
5482
- // Note here that we use the urlHandlingStrategy to get the reset `rawUrlTree` because it may be
5483
- // configured to handle only part of the navigation URL. This means we would only want to reset
5484
- // the part of the navigation handled by the Angular router rather than the whole URL. In
5485
- // addition, the URLHandlingStrategy may be configured to specifically preserve parts of the URL
5486
- // when merging, such as the query params so they are not lost on a refresh.
5487
- this.rawUrlTree = this.urlHandlingStrategy.merge(this.currentUrlTree, t.rawUrl);
5488
- }
5489
- resetUrlToCurrentUrlTree() {
5490
- this.location.replaceState(this.urlSerializer.serialize(this.rawUrlTree), '', this.generateNgRouterState(this.lastSuccessfulId, this.currentPageId));
5491
- }
5492
- generateNgRouterState(navigationId, routerPageId) {
5493
- if (this.canceledNavigationResolution === 'computed') {
5494
- return { navigationId, ɵrouterPageId: routerPageId };
5495
- }
5496
- return { navigationId };
5497
- }
5498
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: Router, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
5499
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: Router, providedIn: 'root' }); }
5519
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: Router, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
5520
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: Router, providedIn: 'root' }); }
5500
5521
  }
5501
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: Router, decorators: [{
5522
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: Router, decorators: [{
5502
5523
  type: Injectable,
5503
5524
  args: [{ providedIn: 'root' }]
5504
5525
  }], ctorParameters: function () { return []; } });
@@ -5769,10 +5790,10 @@ class RouterLink {
5769
5790
  preserveFragment: this.preserveFragment,
5770
5791
  });
5771
5792
  }
5772
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: RouterLink, deps: [{ token: Router }, { token: ActivatedRoute }, { token: 'tabindex', attribute: true }, { token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i3.LocationStrategy }], target: i0.ɵɵFactoryTarget.Directive }); }
5773
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "17.0.0-next.1", type: RouterLink, isStandalone: true, selector: "[routerLink]", inputs: { target: "target", queryParams: "queryParams", fragment: "fragment", queryParamsHandling: "queryParamsHandling", state: "state", relativeTo: "relativeTo", preserveFragment: ["preserveFragment", "preserveFragment", booleanAttribute], skipLocationChange: ["skipLocationChange", "skipLocationChange", booleanAttribute], replaceUrl: ["replaceUrl", "replaceUrl", booleanAttribute], routerLink: "routerLink" }, host: { listeners: { "click": "onClick($event.button,$event.ctrlKey,$event.shiftKey,$event.altKey,$event.metaKey)" }, properties: { "attr.target": "this.target" } }, usesOnChanges: true, ngImport: i0 }); }
5793
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: RouterLink, deps: [{ token: Router }, { token: ActivatedRoute }, { token: 'tabindex', attribute: true }, { token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i3.LocationStrategy }], target: i0.ɵɵFactoryTarget.Directive }); }
5794
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "17.0.0-next.3", type: RouterLink, isStandalone: true, selector: "[routerLink]", inputs: { target: "target", queryParams: "queryParams", fragment: "fragment", queryParamsHandling: "queryParamsHandling", state: "state", relativeTo: "relativeTo", preserveFragment: ["preserveFragment", "preserveFragment", booleanAttribute], skipLocationChange: ["skipLocationChange", "skipLocationChange", booleanAttribute], replaceUrl: ["replaceUrl", "replaceUrl", booleanAttribute], routerLink: "routerLink" }, host: { listeners: { "click": "onClick($event.button,$event.ctrlKey,$event.shiftKey,$event.altKey,$event.metaKey)" }, properties: { "attr.target": "this.target" } }, usesOnChanges: true, ngImport: i0 }); }
5774
5795
  }
5775
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: RouterLink, decorators: [{
5796
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: RouterLink, decorators: [{
5776
5797
  type: Directive,
5777
5798
  args: [{
5778
5799
  selector: '[routerLink]',
@@ -5995,10 +6016,10 @@ class RouterLinkActive {
5995
6016
  const isActiveCheckFn = this.isLinkActive(this.router);
5996
6017
  return this.link && isActiveCheckFn(this.link) || this.links.some(isActiveCheckFn);
5997
6018
  }
5998
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: RouterLinkActive, deps: [{ token: Router }, { token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }, { token: RouterLink, optional: true }], target: i0.ɵɵFactoryTarget.Directive }); }
5999
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.0-next.1", type: RouterLinkActive, isStandalone: true, selector: "[routerLinkActive]", inputs: { routerLinkActiveOptions: "routerLinkActiveOptions", ariaCurrentWhenActive: "ariaCurrentWhenActive", routerLinkActive: "routerLinkActive" }, outputs: { isActiveChange: "isActiveChange" }, queries: [{ propertyName: "links", predicate: RouterLink, descendants: true }], exportAs: ["routerLinkActive"], usesOnChanges: true, ngImport: i0 }); }
6019
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: RouterLinkActive, deps: [{ token: Router }, { token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }, { token: RouterLink, optional: true }], target: i0.ɵɵFactoryTarget.Directive }); }
6020
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.0-next.3", type: RouterLinkActive, isStandalone: true, selector: "[routerLinkActive]", inputs: { routerLinkActiveOptions: "routerLinkActiveOptions", ariaCurrentWhenActive: "ariaCurrentWhenActive", routerLinkActive: "routerLinkActive" }, outputs: { isActiveChange: "isActiveChange" }, queries: [{ propertyName: "links", predicate: RouterLink, descendants: true }], exportAs: ["routerLinkActive"], usesOnChanges: true, ngImport: i0 }); }
6000
6021
  }
6001
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: RouterLinkActive, decorators: [{
6022
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: RouterLinkActive, decorators: [{
6002
6023
  type: Directive,
6003
6024
  args: [{
6004
6025
  selector: '[routerLinkActive]',
@@ -6050,10 +6071,10 @@ class PreloadAllModules {
6050
6071
  preload(route, fn) {
6051
6072
  return fn().pipe(catchError(() => of(null)));
6052
6073
  }
6053
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: PreloadAllModules, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
6054
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: PreloadAllModules, providedIn: 'root' }); }
6074
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: PreloadAllModules, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
6075
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: PreloadAllModules, providedIn: 'root' }); }
6055
6076
  }
6056
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: PreloadAllModules, decorators: [{
6077
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: PreloadAllModules, decorators: [{
6057
6078
  type: Injectable,
6058
6079
  args: [{ providedIn: 'root' }]
6059
6080
  }] });
@@ -6070,10 +6091,10 @@ class NoPreloading {
6070
6091
  preload(route, fn) {
6071
6092
  return of(null);
6072
6093
  }
6073
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: NoPreloading, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
6074
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: NoPreloading, providedIn: 'root' }); }
6094
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: NoPreloading, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
6095
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: NoPreloading, providedIn: 'root' }); }
6075
6096
  }
6076
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: NoPreloading, decorators: [{
6097
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: NoPreloading, decorators: [{
6077
6098
  type: Injectable,
6078
6099
  args: [{ providedIn: 'root' }]
6079
6100
  }] });
@@ -6166,10 +6187,10 @@ class RouterPreloader {
6166
6187
  }
6167
6188
  });
6168
6189
  }
6169
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: RouterPreloader, deps: [{ token: Router }, { token: i0.Compiler }, { token: i0.EnvironmentInjector }, { token: PreloadingStrategy }, { token: RouterConfigLoader }], target: i0.ɵɵFactoryTarget.Injectable }); }
6170
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: RouterPreloader, providedIn: 'root' }); }
6190
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: RouterPreloader, deps: [{ token: Router }, { token: i0.Compiler }, { token: i0.EnvironmentInjector }, { token: PreloadingStrategy }, { token: RouterConfigLoader }], target: i0.ɵɵFactoryTarget.Injectable }); }
6191
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: RouterPreloader, providedIn: 'root' }); }
6171
6192
  }
6172
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: RouterPreloader, decorators: [{
6193
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: RouterPreloader, decorators: [{
6173
6194
  type: Injectable,
6174
6195
  args: [{ providedIn: 'root' }]
6175
6196
  }], ctorParameters: function () { return [{ type: Router }, { type: i0.Compiler }, { type: i0.EnvironmentInjector }, { type: PreloadingStrategy }, { type: RouterConfigLoader }]; } });
@@ -6262,10 +6283,10 @@ class RouterScroller {
6262
6283
  this.routerEventsSubscription?.unsubscribe();
6263
6284
  this.scrollEventsSubscription?.unsubscribe();
6264
6285
  }
6265
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: RouterScroller, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable }); }
6266
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: RouterScroller }); }
6286
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: RouterScroller, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable }); }
6287
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: RouterScroller }); }
6267
6288
  }
6268
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: RouterScroller, decorators: [{
6289
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: RouterScroller, decorators: [{
6269
6290
  type: Injectable
6270
6291
  }], ctorParameters: function () { return [{ type: UrlSerializer }, { type: NavigationTransitions }, { type: i3.ViewportScroller }, { type: i0.NgZone }, { type: undefined }]; } });
6271
6292
 
@@ -6872,11 +6893,11 @@ class RouterModule {
6872
6893
  providers: [{ provide: ROUTES, multi: true, useValue: routes }],
6873
6894
  };
6874
6895
  }
6875
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: RouterModule, deps: [{ token: ROUTER_FORROOT_GUARD, optional: true }], target: i0.ɵɵFactoryTarget.NgModule }); }
6876
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.0.0-next.1", ngImport: i0, type: RouterModule, imports: [RouterOutlet, RouterLink, RouterLinkActive, ɵEmptyOutletComponent], exports: [RouterOutlet, RouterLink, RouterLinkActive, ɵEmptyOutletComponent] }); }
6877
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: RouterModule }); }
6896
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: RouterModule, deps: [{ token: ROUTER_FORROOT_GUARD, optional: true }], target: i0.ɵɵFactoryTarget.NgModule }); }
6897
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.0.0-next.3", ngImport: i0, type: RouterModule, imports: [RouterOutlet, RouterLink, RouterLinkActive, ɵEmptyOutletComponent], exports: [RouterOutlet, RouterLink, RouterLinkActive, ɵEmptyOutletComponent] }); }
6898
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: RouterModule }); }
6878
6899
  }
6879
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.1", ngImport: i0, type: RouterModule, decorators: [{
6900
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.3", ngImport: i0, type: RouterModule, decorators: [{
6880
6901
  type: NgModule,
6881
6902
  args: [{
6882
6903
  imports: ROUTER_DIRECTIVES,
@@ -7021,7 +7042,7 @@ function mapToResolve(provider) {
7021
7042
  /**
7022
7043
  * @publicApi
7023
7044
  */
7024
- const VERSION = new Version('17.0.0-next.1');
7045
+ const VERSION = new Version('17.0.0-next.3');
7025
7046
 
7026
7047
  /**
7027
7048
  * @module