@angular/router 15.0.0 → 15.0.2
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.
- package/esm2020/src/components/empty_outlet.mjs +3 -3
- package/esm2020/src/deprecated_load_children.mjs +3 -1
- package/esm2020/src/directives/router_link.mjs +3 -3
- package/esm2020/src/directives/router_link_active.mjs +3 -3
- package/esm2020/src/directives/router_outlet.mjs +5 -5
- package/esm2020/src/index.mjs +1 -1
- package/esm2020/src/models.mjs +1 -1
- package/esm2020/src/navigation_transition.mjs +380 -0
- package/esm2020/src/operators/activate_routes.mjs +1 -1
- package/esm2020/src/operators/apply_redirects.mjs +1 -1
- package/esm2020/src/operators/check_guards.mjs +1 -1
- package/esm2020/src/operators/recognize.mjs +1 -1
- package/esm2020/src/operators/resolve_data.mjs +1 -1
- package/esm2020/src/page_title_strategy.mjs +6 -6
- package/esm2020/src/private_export.mjs +1 -1
- package/esm2020/src/provide_router.mjs +11 -15
- package/esm2020/src/route_reuse_strategy.mjs +15 -1
- package/esm2020/src/router.mjs +76 -407
- package/esm2020/src/router_config_loader.mjs +3 -3
- package/esm2020/src/router_module.mjs +9 -7
- package/esm2020/src/router_outlet_context.mjs +3 -3
- package/esm2020/src/router_preloader.mjs +9 -9
- package/esm2020/src/router_scroller.mjs +20 -21
- package/esm2020/src/router_state.mjs +1 -1
- package/esm2020/src/url_handling_strategy.mjs +15 -1
- package/esm2020/src/url_tree.mjs +4 -4
- package/esm2020/src/version.mjs +1 -1
- package/esm2020/testing/src/router_testing_module.mjs +4 -4
- package/fesm2015/router.mjs +790 -732
- package/fesm2015/router.mjs.map +1 -1
- package/fesm2015/testing.mjs +5 -5
- package/fesm2015/upgrade.mjs +1 -1
- package/fesm2020/router.mjs +794 -735
- package/fesm2020/router.mjs.map +1 -1
- package/fesm2020/testing.mjs +5 -5
- package/fesm2020/upgrade.mjs +1 -1
- package/index.d.ts +24 -80
- package/package.json +4 -4
- package/testing/index.d.ts +1 -1
- package/upgrade/index.d.ts +1 -1
package/fesm2020/router.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular v15.0.
|
|
2
|
+
* @license Angular v15.0.2
|
|
3
3
|
* (c) 2010-2022 Google LLC. https://angular.io/
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import * as i0 from '@angular/core';
|
|
8
|
-
import { ɵisObservable, ɵisPromise, ɵRuntimeError, Injectable, EventEmitter, inject, ViewContainerRef, ChangeDetectorRef, EnvironmentInjector, Directive, Input, Output, Component, createEnvironmentInjector, ɵisStandalone, ComponentFactoryResolver, ɵisInjectable, InjectionToken, InjectFlags, NgModuleFactory, Injector, Compiler,
|
|
8
|
+
import { ɵisObservable, ɵisPromise, ɵRuntimeError, Injectable, EventEmitter, inject, ViewContainerRef, ChangeDetectorRef, EnvironmentInjector, Directive, Input, Output, Component, createEnvironmentInjector, ɵisStandalone, ComponentFactoryResolver, ɵisInjectable, InjectionToken, InjectFlags, NgModuleFactory, Injector, Compiler, ɵConsole, NgZone, ɵcoerceToBoolean, ɵɵsanitizeUrlOrResourceUrl, Attribute, HostBinding, HostListener, Optional, ContentChildren, makeEnvironmentProviders, APP_BOOTSTRAP_LISTENER, ENVIRONMENT_INITIALIZER, ApplicationRef, APP_INITIALIZER, NgProbeToken, SkipSelf, NgModule, Inject, Version } from '@angular/core';
|
|
9
9
|
import { from, of, BehaviorSubject, EmptyError, combineLatest, concat, defer, pipe, throwError, Observable, EMPTY, ConnectableObservable, Subject } from 'rxjs';
|
|
10
10
|
import * as i3 from '@angular/common';
|
|
11
11
|
import { Location, ViewportScroller, LOCATION_INITIALIZED, LocationStrategy, HashLocationStrategy, PathLocationStrategy } from '@angular/common';
|
|
@@ -202,7 +202,7 @@ function wrapIntoObservable(value) {
|
|
|
202
202
|
* Use of this source code is governed by an MIT-style license that can be
|
|
203
203
|
* found in the LICENSE file at https://angular.io/license
|
|
204
204
|
*/
|
|
205
|
-
const NG_DEV_MODE$
|
|
205
|
+
const NG_DEV_MODE$a = typeof ngDevMode === 'undefined' || ngDevMode;
|
|
206
206
|
const pathCompareMap = {
|
|
207
207
|
'exact': equalSegmentGroups,
|
|
208
208
|
'subset': containsSegmentGroup,
|
|
@@ -327,7 +327,7 @@ class UrlTree {
|
|
|
327
327
|
this.root = root;
|
|
328
328
|
this.queryParams = queryParams;
|
|
329
329
|
this.fragment = fragment;
|
|
330
|
-
if (NG_DEV_MODE$
|
|
330
|
+
if (NG_DEV_MODE$a) {
|
|
331
331
|
if (root.segments.length > 0) {
|
|
332
332
|
throw new ɵRuntimeError(4015 /* RuntimeErrorCode.INVALID_ROOT_URL_SEGMENT */, 'The root `UrlSegmentGroup` should not contain `segments`. ' +
|
|
333
333
|
'Instead, these segments belong in the `children` so they can be associated with a named outlet.');
|
|
@@ -461,9 +461,9 @@ function mapChildrenIntoArray(segment, fn) {
|
|
|
461
461
|
*/
|
|
462
462
|
class UrlSerializer {
|
|
463
463
|
}
|
|
464
|
-
UrlSerializer.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.
|
|
465
|
-
UrlSerializer.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.
|
|
466
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.
|
|
464
|
+
UrlSerializer.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: UrlSerializer, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
465
|
+
UrlSerializer.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: UrlSerializer, providedIn: 'root', useFactory: () => new DefaultUrlSerializer() });
|
|
466
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: UrlSerializer, decorators: [{
|
|
467
467
|
type: Injectable,
|
|
468
468
|
args: [{ providedIn: 'root', useFactory: () => new DefaultUrlSerializer() }]
|
|
469
469
|
}] });
|
|
@@ -675,7 +675,7 @@ class UrlParser {
|
|
|
675
675
|
parseSegment() {
|
|
676
676
|
const path = matchSegments(this.remaining);
|
|
677
677
|
if (path === '' && this.peekStartsWith(';')) {
|
|
678
|
-
throw new ɵRuntimeError(4009 /* RuntimeErrorCode.EMPTY_PATH_WITH_PARAMS */, NG_DEV_MODE$
|
|
678
|
+
throw new ɵRuntimeError(4009 /* RuntimeErrorCode.EMPTY_PATH_WITH_PARAMS */, NG_DEV_MODE$a && `Empty path url segment cannot have parameters: '${this.remaining}'.`);
|
|
679
679
|
}
|
|
680
680
|
this.capture(path);
|
|
681
681
|
return new UrlSegment(decode(path), this.parseMatrixParams());
|
|
@@ -744,7 +744,7 @@ class UrlParser {
|
|
|
744
744
|
// if is is not one of these characters, then the segment was unescaped
|
|
745
745
|
// or the group was not closed
|
|
746
746
|
if (next !== '/' && next !== ')' && next !== ';') {
|
|
747
|
-
throw new ɵRuntimeError(4010 /* RuntimeErrorCode.UNPARSABLE_URL */, NG_DEV_MODE$
|
|
747
|
+
throw new ɵRuntimeError(4010 /* RuntimeErrorCode.UNPARSABLE_URL */, NG_DEV_MODE$a && `Cannot parse url '${this.url}'`);
|
|
748
748
|
}
|
|
749
749
|
let outletName = undefined;
|
|
750
750
|
if (path.indexOf(':') > -1) {
|
|
@@ -775,7 +775,7 @@ class UrlParser {
|
|
|
775
775
|
}
|
|
776
776
|
capture(str) {
|
|
777
777
|
if (!this.consumeOptional(str)) {
|
|
778
|
-
throw new ɵRuntimeError(4011 /* RuntimeErrorCode.UNEXPECTED_VALUE_IN_URL */, NG_DEV_MODE$
|
|
778
|
+
throw new ɵRuntimeError(4011 /* RuntimeErrorCode.UNEXPECTED_VALUE_IN_URL */, NG_DEV_MODE$a && `Expected "${str}".`);
|
|
779
779
|
}
|
|
780
780
|
}
|
|
781
781
|
}
|
|
@@ -828,7 +828,7 @@ function isUrlTree(v) {
|
|
|
828
828
|
* Use of this source code is governed by an MIT-style license that can be
|
|
829
829
|
* found in the LICENSE file at https://angular.io/license
|
|
830
830
|
*/
|
|
831
|
-
const NG_DEV_MODE$
|
|
831
|
+
const NG_DEV_MODE$9 = typeof ngDevMode === 'undefined' || ngDevMode;
|
|
832
832
|
/**
|
|
833
833
|
* Creates a `UrlTree` relative to an `ActivatedRouteSnapshot`.
|
|
834
834
|
*
|
|
@@ -997,11 +997,11 @@ class Navigation {
|
|
|
997
997
|
this.numberOfDoubleDots = numberOfDoubleDots;
|
|
998
998
|
this.commands = commands;
|
|
999
999
|
if (isAbsolute && commands.length > 0 && isMatrixParams(commands[0])) {
|
|
1000
|
-
throw new ɵRuntimeError(4003 /* RuntimeErrorCode.ROOT_SEGMENT_MATRIX_PARAMS */, NG_DEV_MODE$
|
|
1000
|
+
throw new ɵRuntimeError(4003 /* RuntimeErrorCode.ROOT_SEGMENT_MATRIX_PARAMS */, NG_DEV_MODE$9 && 'Root segment cannot have matrix parameters');
|
|
1001
1001
|
}
|
|
1002
1002
|
const cmdWithOutlet = commands.find(isCommandWithOutlets);
|
|
1003
1003
|
if (cmdWithOutlet && cmdWithOutlet !== last(commands)) {
|
|
1004
|
-
throw new ɵRuntimeError(4004 /* RuntimeErrorCode.MISPLACED_OUTLETS_COMMAND */, NG_DEV_MODE$
|
|
1004
|
+
throw new ɵRuntimeError(4004 /* RuntimeErrorCode.MISPLACED_OUTLETS_COMMAND */, NG_DEV_MODE$9 && '{outlets:{}} has to be the last command');
|
|
1005
1005
|
}
|
|
1006
1006
|
}
|
|
1007
1007
|
toRoot() {
|
|
@@ -1100,7 +1100,7 @@ function createPositionApplyingDoubleDots(group, index, numberOfDoubleDots) {
|
|
|
1100
1100
|
dd -= ci;
|
|
1101
1101
|
g = g.parent;
|
|
1102
1102
|
if (!g) {
|
|
1103
|
-
throw new ɵRuntimeError(4005 /* RuntimeErrorCode.INVALID_DOUBLE_DOTS */, NG_DEV_MODE$
|
|
1103
|
+
throw new ɵRuntimeError(4005 /* RuntimeErrorCode.INVALID_DOUBLE_DOTS */, NG_DEV_MODE$9 && 'Invalid number of \'../\'');
|
|
1104
1104
|
}
|
|
1105
1105
|
ci = g.segments.length;
|
|
1106
1106
|
}
|
|
@@ -2380,9 +2380,9 @@ class ChildrenOutletContexts {
|
|
|
2380
2380
|
return this.contexts.get(childName) || null;
|
|
2381
2381
|
}
|
|
2382
2382
|
}
|
|
2383
|
-
ChildrenOutletContexts.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.
|
|
2384
|
-
ChildrenOutletContexts.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.
|
|
2385
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.
|
|
2383
|
+
ChildrenOutletContexts.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: ChildrenOutletContexts, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2384
|
+
ChildrenOutletContexts.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: ChildrenOutletContexts, providedIn: 'root' });
|
|
2385
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: ChildrenOutletContexts, decorators: [{
|
|
2386
2386
|
type: Injectable,
|
|
2387
2387
|
args: [{ providedIn: 'root' }]
|
|
2388
2388
|
}] });
|
|
@@ -2394,7 +2394,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImpor
|
|
|
2394
2394
|
* Use of this source code is governed by an MIT-style license that can be
|
|
2395
2395
|
* found in the LICENSE file at https://angular.io/license
|
|
2396
2396
|
*/
|
|
2397
|
-
const NG_DEV_MODE$
|
|
2397
|
+
const NG_DEV_MODE$8 = typeof ngDevMode === 'undefined' || ngDevMode;
|
|
2398
2398
|
/**
|
|
2399
2399
|
* @description
|
|
2400
2400
|
*
|
|
@@ -2533,12 +2533,12 @@ class RouterOutlet {
|
|
|
2533
2533
|
*/
|
|
2534
2534
|
get component() {
|
|
2535
2535
|
if (!this.activated)
|
|
2536
|
-
throw new ɵRuntimeError(4012 /* RuntimeErrorCode.OUTLET_NOT_ACTIVATED */, NG_DEV_MODE$
|
|
2536
|
+
throw new ɵRuntimeError(4012 /* RuntimeErrorCode.OUTLET_NOT_ACTIVATED */, NG_DEV_MODE$8 && 'Outlet is not activated');
|
|
2537
2537
|
return this.activated.instance;
|
|
2538
2538
|
}
|
|
2539
2539
|
get activatedRoute() {
|
|
2540
2540
|
if (!this.activated)
|
|
2541
|
-
throw new ɵRuntimeError(4012 /* RuntimeErrorCode.OUTLET_NOT_ACTIVATED */, NG_DEV_MODE$
|
|
2541
|
+
throw new ɵRuntimeError(4012 /* RuntimeErrorCode.OUTLET_NOT_ACTIVATED */, NG_DEV_MODE$8 && 'Outlet is not activated');
|
|
2542
2542
|
return this._activatedRoute;
|
|
2543
2543
|
}
|
|
2544
2544
|
get activatedRouteData() {
|
|
@@ -2552,7 +2552,7 @@ class RouterOutlet {
|
|
|
2552
2552
|
*/
|
|
2553
2553
|
detach() {
|
|
2554
2554
|
if (!this.activated)
|
|
2555
|
-
throw new ɵRuntimeError(4012 /* RuntimeErrorCode.OUTLET_NOT_ACTIVATED */, NG_DEV_MODE$
|
|
2555
|
+
throw new ɵRuntimeError(4012 /* RuntimeErrorCode.OUTLET_NOT_ACTIVATED */, NG_DEV_MODE$8 && 'Outlet is not activated');
|
|
2556
2556
|
this.location.detach();
|
|
2557
2557
|
const cmp = this.activated;
|
|
2558
2558
|
this.activated = null;
|
|
@@ -2580,11 +2580,11 @@ class RouterOutlet {
|
|
|
2580
2580
|
}
|
|
2581
2581
|
activateWith(activatedRoute, resolverOrInjector) {
|
|
2582
2582
|
if (this.isActivated) {
|
|
2583
|
-
throw new ɵRuntimeError(4013 /* RuntimeErrorCode.OUTLET_ALREADY_ACTIVATED */, NG_DEV_MODE$
|
|
2583
|
+
throw new ɵRuntimeError(4013 /* RuntimeErrorCode.OUTLET_ALREADY_ACTIVATED */, NG_DEV_MODE$8 && 'Cannot activate an already activated outlet');
|
|
2584
2584
|
}
|
|
2585
2585
|
this._activatedRoute = activatedRoute;
|
|
2586
2586
|
const location = this.location;
|
|
2587
|
-
const snapshot = activatedRoute.
|
|
2587
|
+
const snapshot = activatedRoute.snapshot;
|
|
2588
2588
|
const component = snapshot.component;
|
|
2589
2589
|
const childContexts = this.parentContexts.getOrCreateContext(this.name).children;
|
|
2590
2590
|
const injector = new OutletInjector(activatedRoute, childContexts, location.injector);
|
|
@@ -2602,9 +2602,9 @@ class RouterOutlet {
|
|
|
2602
2602
|
this.activateEvents.emit(this.activated.instance);
|
|
2603
2603
|
}
|
|
2604
2604
|
}
|
|
2605
|
-
RouterOutlet.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.
|
|
2606
|
-
RouterOutlet.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.0.
|
|
2607
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.
|
|
2605
|
+
RouterOutlet.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: RouterOutlet, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
2606
|
+
RouterOutlet.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.0.2", 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 });
|
|
2607
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: RouterOutlet, decorators: [{
|
|
2608
2608
|
type: Directive,
|
|
2609
2609
|
args: [{
|
|
2610
2610
|
selector: 'router-outlet',
|
|
@@ -2664,9 +2664,9 @@ function isComponentFactoryResolver(item) {
|
|
|
2664
2664
|
*/
|
|
2665
2665
|
class ɵEmptyOutletComponent {
|
|
2666
2666
|
}
|
|
2667
|
-
ɵEmptyOutletComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.
|
|
2668
|
-
ɵEmptyOutletComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.
|
|
2669
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.
|
|
2667
|
+
ɵEmptyOutletComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: ɵEmptyOutletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2668
|
+
ɵEmptyOutletComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.2", 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"] }] });
|
|
2669
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: ɵEmptyOutletComponent, decorators: [{
|
|
2670
2670
|
type: Component,
|
|
2671
2671
|
args: [{
|
|
2672
2672
|
template: `<router-outlet></router-outlet>`,
|
|
@@ -3578,7 +3578,7 @@ function noLeftoversInUrl(segmentGroup, segments, outlet) {
|
|
|
3578
3578
|
* Use of this source code is governed by an MIT-style license that can be
|
|
3579
3579
|
* found in the LICENSE file at https://angular.io/license
|
|
3580
3580
|
*/
|
|
3581
|
-
const NG_DEV_MODE$
|
|
3581
|
+
const NG_DEV_MODE$7 = typeof ngDevMode === 'undefined' || ngDevMode;
|
|
3582
3582
|
class NoMatch$1 {
|
|
3583
3583
|
constructor(segmentGroup) {
|
|
3584
3584
|
this.segmentGroup = segmentGroup || null;
|
|
@@ -3596,11 +3596,11 @@ function absoluteRedirect(newTree) {
|
|
|
3596
3596
|
return throwError(new AbsoluteRedirect(newTree));
|
|
3597
3597
|
}
|
|
3598
3598
|
function namedOutletsRedirect(redirectTo) {
|
|
3599
|
-
return throwError(new ɵRuntimeError(4000 /* RuntimeErrorCode.NAMED_OUTLET_REDIRECT */, NG_DEV_MODE$
|
|
3599
|
+
return throwError(new ɵRuntimeError(4000 /* RuntimeErrorCode.NAMED_OUTLET_REDIRECT */, NG_DEV_MODE$7 &&
|
|
3600
3600
|
`Only absolute redirects can have named outlets. redirectTo: '${redirectTo}'`));
|
|
3601
3601
|
}
|
|
3602
3602
|
function canLoadFails(route) {
|
|
3603
|
-
return throwError(navigationCancelingError(NG_DEV_MODE$
|
|
3603
|
+
return throwError(navigationCancelingError(NG_DEV_MODE$7 &&
|
|
3604
3604
|
`Cannot load children because the guard of the route "path: '${route.path}'" returned false`, 3 /* NavigationCancellationCode.GuardRejected */));
|
|
3605
3605
|
}
|
|
3606
3606
|
/**
|
|
@@ -3660,7 +3660,7 @@ class ApplyRedirects {
|
|
|
3660
3660
|
}));
|
|
3661
3661
|
}
|
|
3662
3662
|
noMatchError(e) {
|
|
3663
|
-
return new ɵRuntimeError(4002 /* RuntimeErrorCode.NO_MATCH */, NG_DEV_MODE$
|
|
3663
|
+
return new ɵRuntimeError(4002 /* RuntimeErrorCode.NO_MATCH */, NG_DEV_MODE$7 && `Cannot match any routes. URL Segment: '${e.segmentGroup}'`);
|
|
3664
3664
|
}
|
|
3665
3665
|
createUrlTree(rootCandidate, queryParams, fragment) {
|
|
3666
3666
|
const root = createRoot(rootCandidate);
|
|
@@ -3875,7 +3875,7 @@ class ApplyRedirects {
|
|
|
3875
3875
|
findPosParam(redirectTo, redirectToUrlSegment, posParams) {
|
|
3876
3876
|
const pos = posParams[redirectToUrlSegment.path.substring(1)];
|
|
3877
3877
|
if (!pos)
|
|
3878
|
-
throw new ɵRuntimeError(4001 /* RuntimeErrorCode.MISSING_REDIRECT */, NG_DEV_MODE$
|
|
3878
|
+
throw new ɵRuntimeError(4001 /* RuntimeErrorCode.MISSING_REDIRECT */, NG_DEV_MODE$7 &&
|
|
3879
3879
|
`Cannot redirect to '${redirectTo}'. Cannot find '${redirectToUrlSegment.path}'.`);
|
|
3880
3880
|
return pos;
|
|
3881
3881
|
}
|
|
@@ -3911,7 +3911,7 @@ function applyRedirects(environmentInjector, configLoader, urlSerializer, config
|
|
|
3911
3911
|
* Use of this source code is governed by an MIT-style license that can be
|
|
3912
3912
|
* found in the LICENSE file at https://angular.io/license
|
|
3913
3913
|
*/
|
|
3914
|
-
const NG_DEV_MODE$
|
|
3914
|
+
const NG_DEV_MODE$6 = typeof ngDevMode === 'undefined' || !!ngDevMode;
|
|
3915
3915
|
class NoMatch {
|
|
3916
3916
|
}
|
|
3917
3917
|
function newObservableError(e) {
|
|
@@ -3999,7 +3999,7 @@ class Recognizer {
|
|
|
3999
3999
|
// multiple activated results for the same outlet. We should merge the children of
|
|
4000
4000
|
// these results so the final return value is only one `TreeNode` per outlet.
|
|
4001
4001
|
const mergedChildren = mergeEmptyPathMatches(children);
|
|
4002
|
-
if (NG_DEV_MODE$
|
|
4002
|
+
if (NG_DEV_MODE$6) {
|
|
4003
4003
|
// This should really never happen - we are only taking the first match for each
|
|
4004
4004
|
// outlet and merge the empty path matches.
|
|
4005
4005
|
checkOutletNameUniqueness(mergedChildren);
|
|
@@ -4154,7 +4154,7 @@ function checkOutletNameUniqueness(nodes) {
|
|
|
4154
4154
|
if (routeWithSameOutletName) {
|
|
4155
4155
|
const p = routeWithSameOutletName.url.map(s => s.toString()).join('/');
|
|
4156
4156
|
const c = n.value.url.map(s => s.toString()).join('/');
|
|
4157
|
-
throw new ɵRuntimeError(4006 /* RuntimeErrorCode.TWO_SEGMENTS_WITH_SAME_OUTLET */, NG_DEV_MODE$
|
|
4157
|
+
throw new ɵRuntimeError(4006 /* RuntimeErrorCode.TWO_SEGMENTS_WITH_SAME_OUTLET */, NG_DEV_MODE$6 && `Two segments cannot have the same outlet name: '${p}' and '${c}'.`);
|
|
4158
4158
|
}
|
|
4159
4159
|
names[n.value.outlet] = n.value;
|
|
4160
4160
|
});
|
|
@@ -4292,173 +4292,8 @@ function switchTap(next) {
|
|
|
4292
4292
|
* Use of this source code is governed by an MIT-style license that can be
|
|
4293
4293
|
* found in the LICENSE file at https://angular.io/license
|
|
4294
4294
|
*/
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
*
|
|
4298
|
-
* The built-in implementation traverses the router state snapshot and finds the deepest primary
|
|
4299
|
-
* outlet with `title` property. Given the `Routes` below, navigating to
|
|
4300
|
-
* `/base/child(popup:aux)` would result in the document title being set to "child".
|
|
4301
|
-
* ```
|
|
4302
|
-
* [
|
|
4303
|
-
* {path: 'base', title: 'base', children: [
|
|
4304
|
-
* {path: 'child', title: 'child'},
|
|
4305
|
-
* ],
|
|
4306
|
-
* {path: 'aux', outlet: 'popup', title: 'popupTitle'}
|
|
4307
|
-
* ]
|
|
4308
|
-
* ```
|
|
4309
|
-
*
|
|
4310
|
-
* This class can be used as a base class for custom title strategies. That is, you can create your
|
|
4311
|
-
* own class that extends the `TitleStrategy`. Note that in the above example, the `title`
|
|
4312
|
-
* from the named outlet is never used. However, a custom strategy might be implemented to
|
|
4313
|
-
* incorporate titles in named outlets.
|
|
4314
|
-
*
|
|
4315
|
-
* @publicApi
|
|
4316
|
-
* @see [Page title guide](guide/router#setting-the-page-title)
|
|
4317
|
-
*/
|
|
4318
|
-
class TitleStrategy {
|
|
4319
|
-
/**
|
|
4320
|
-
* @returns The `title` of the deepest primary route.
|
|
4321
|
-
*/
|
|
4322
|
-
buildTitle(snapshot) {
|
|
4323
|
-
let pageTitle;
|
|
4324
|
-
let route = snapshot.root;
|
|
4325
|
-
while (route !== undefined) {
|
|
4326
|
-
pageTitle = this.getResolvedTitleForRoute(route) ?? pageTitle;
|
|
4327
|
-
route = route.children.find(child => child.outlet === PRIMARY_OUTLET);
|
|
4328
|
-
}
|
|
4329
|
-
return pageTitle;
|
|
4330
|
-
}
|
|
4331
|
-
/**
|
|
4332
|
-
* Given an `ActivatedRouteSnapshot`, returns the final value of the
|
|
4333
|
-
* `Route.title` property, which can either be a static string or a resolved value.
|
|
4334
|
-
*/
|
|
4335
|
-
getResolvedTitleForRoute(snapshot) {
|
|
4336
|
-
return snapshot.data[RouteTitleKey];
|
|
4337
|
-
}
|
|
4338
|
-
}
|
|
4339
|
-
TitleStrategy.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: TitleStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
4340
|
-
TitleStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: TitleStrategy, providedIn: 'root', useFactory: () => inject(DefaultTitleStrategy) });
|
|
4341
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: TitleStrategy, decorators: [{
|
|
4342
|
-
type: Injectable,
|
|
4343
|
-
args: [{ providedIn: 'root', useFactory: () => inject(DefaultTitleStrategy) }]
|
|
4344
|
-
}] });
|
|
4345
|
-
/**
|
|
4346
|
-
* The default `TitleStrategy` used by the router that updates the title using the `Title` service.
|
|
4347
|
-
*/
|
|
4348
|
-
class DefaultTitleStrategy extends TitleStrategy {
|
|
4349
|
-
constructor(title) {
|
|
4350
|
-
super();
|
|
4351
|
-
this.title = title;
|
|
4352
|
-
}
|
|
4353
|
-
/**
|
|
4354
|
-
* Sets the title of the browser to the given value.
|
|
4355
|
-
*
|
|
4356
|
-
* @param title The `pageTitle` from the deepest primary route.
|
|
4357
|
-
*/
|
|
4358
|
-
updateTitle(snapshot) {
|
|
4359
|
-
const title = this.buildTitle(snapshot);
|
|
4360
|
-
if (title !== undefined) {
|
|
4361
|
-
this.title.setTitle(title);
|
|
4362
|
-
}
|
|
4363
|
-
}
|
|
4364
|
-
}
|
|
4365
|
-
DefaultTitleStrategy.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: DefaultTitleStrategy, deps: [{ token: i1.Title }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
4366
|
-
DefaultTitleStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: DefaultTitleStrategy, providedIn: 'root' });
|
|
4367
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: DefaultTitleStrategy, decorators: [{
|
|
4368
|
-
type: Injectable,
|
|
4369
|
-
args: [{ providedIn: 'root' }]
|
|
4370
|
-
}], ctorParameters: function () { return [{ type: i1.Title }]; } });
|
|
4371
|
-
|
|
4372
|
-
/**
|
|
4373
|
-
* @license
|
|
4374
|
-
* Copyright Google LLC All Rights Reserved.
|
|
4375
|
-
*
|
|
4376
|
-
* Use of this source code is governed by an MIT-style license that can be
|
|
4377
|
-
* found in the LICENSE file at https://angular.io/license
|
|
4378
|
-
*/
|
|
4379
|
-
/**
|
|
4380
|
-
* @description
|
|
4381
|
-
*
|
|
4382
|
-
* Provides a way to customize when activated routes get reused.
|
|
4383
|
-
*
|
|
4384
|
-
* @publicApi
|
|
4385
|
-
*/
|
|
4386
|
-
class RouteReuseStrategy {
|
|
4387
|
-
}
|
|
4388
|
-
/**
|
|
4389
|
-
* @description
|
|
4390
|
-
*
|
|
4391
|
-
* This base route reuse strategy only reuses routes when the matched router configs are
|
|
4392
|
-
* identical. This prevents components from being destroyed and recreated
|
|
4393
|
-
* when just the route parameters, query parameters or fragment change
|
|
4394
|
-
* (that is, the existing component is _reused_).
|
|
4395
|
-
*
|
|
4396
|
-
* This strategy does not store any routes for later reuse.
|
|
4397
|
-
*
|
|
4398
|
-
* Angular uses this strategy by default.
|
|
4399
|
-
*
|
|
4400
|
-
*
|
|
4401
|
-
* It can be used as a base class for custom route reuse strategies, i.e. you can create your own
|
|
4402
|
-
* class that extends the `BaseRouteReuseStrategy` one.
|
|
4403
|
-
* @publicApi
|
|
4404
|
-
*/
|
|
4405
|
-
class BaseRouteReuseStrategy {
|
|
4406
|
-
/**
|
|
4407
|
-
* Whether the given route should detach for later reuse.
|
|
4408
|
-
* Always returns false for `BaseRouteReuseStrategy`.
|
|
4409
|
-
* */
|
|
4410
|
-
shouldDetach(route) {
|
|
4411
|
-
return false;
|
|
4412
|
-
}
|
|
4413
|
-
/**
|
|
4414
|
-
* A no-op; the route is never stored since this strategy never detaches routes for later re-use.
|
|
4415
|
-
*/
|
|
4416
|
-
store(route, detachedTree) { }
|
|
4417
|
-
/** Returns `false`, meaning the route (and its subtree) is never reattached */
|
|
4418
|
-
shouldAttach(route) {
|
|
4419
|
-
return false;
|
|
4420
|
-
}
|
|
4421
|
-
/** Returns `null` because this strategy does not store routes for later re-use. */
|
|
4422
|
-
retrieve(route) {
|
|
4423
|
-
return null;
|
|
4424
|
-
}
|
|
4425
|
-
/**
|
|
4426
|
-
* Determines if a route should be reused.
|
|
4427
|
-
* This strategy returns `true` when the future route config and current route config are
|
|
4428
|
-
* identical.
|
|
4429
|
-
*/
|
|
4430
|
-
shouldReuseRoute(future, curr) {
|
|
4431
|
-
return future.routeConfig === curr.routeConfig;
|
|
4432
|
-
}
|
|
4433
|
-
}
|
|
4434
|
-
class DefaultRouteReuseStrategy extends BaseRouteReuseStrategy {
|
|
4435
|
-
}
|
|
4436
|
-
|
|
4437
|
-
/**
|
|
4438
|
-
* @license
|
|
4439
|
-
* Copyright Google LLC All Rights Reserved.
|
|
4440
|
-
*
|
|
4441
|
-
* Use of this source code is governed by an MIT-style license that can be
|
|
4442
|
-
* found in the LICENSE file at https://angular.io/license
|
|
4443
|
-
*/
|
|
4444
|
-
const NG_DEV_MODE$4 = typeof ngDevMode === 'undefined' || !!ngDevMode;
|
|
4445
|
-
/**
|
|
4446
|
-
* A [DI token](guide/glossary/#di-token) for the router service.
|
|
4447
|
-
*
|
|
4448
|
-
* @publicApi
|
|
4449
|
-
*/
|
|
4450
|
-
const ROUTER_CONFIGURATION = new InjectionToken(NG_DEV_MODE$4 ? 'router config' : '', {
|
|
4451
|
-
providedIn: 'root',
|
|
4452
|
-
factory: () => ({}),
|
|
4453
|
-
});
|
|
4454
|
-
|
|
4455
|
-
/**
|
|
4456
|
-
* @license
|
|
4457
|
-
* Copyright Google LLC All Rights Reserved.
|
|
4458
|
-
*
|
|
4459
|
-
* Use of this source code is governed by an MIT-style license that can be
|
|
4460
|
-
* found in the LICENSE file at https://angular.io/license
|
|
4461
|
-
*/
|
|
4295
|
+
// This file exists to support the legacy `loadChildren: string` behavior being patched back into
|
|
4296
|
+
// Angular.
|
|
4462
4297
|
function deprecatedLoadChildrenString(injector, loadChildren) {
|
|
4463
4298
|
return null;
|
|
4464
4299
|
}
|
|
@@ -4470,7 +4305,7 @@ function deprecatedLoadChildrenString(injector, loadChildren) {
|
|
|
4470
4305
|
* Use of this source code is governed by an MIT-style license that can be
|
|
4471
4306
|
* found in the LICENSE file at https://angular.io/license
|
|
4472
4307
|
*/
|
|
4473
|
-
const NG_DEV_MODE$
|
|
4308
|
+
const NG_DEV_MODE$5 = typeof ngDevMode === 'undefined' || !!ngDevMode;
|
|
4474
4309
|
/**
|
|
4475
4310
|
* The [DI token](guide/glossary/#di-token) for a router configuration.
|
|
4476
4311
|
*
|
|
@@ -4504,7 +4339,7 @@ class RouterConfigLoader {
|
|
|
4504
4339
|
if (this.onLoadEndListener) {
|
|
4505
4340
|
this.onLoadEndListener(route);
|
|
4506
4341
|
}
|
|
4507
|
-
NG_DEV_MODE$
|
|
4342
|
+
NG_DEV_MODE$5 && assertStandalone(route.path ?? '', component);
|
|
4508
4343
|
route._loadedComponent = component;
|
|
4509
4344
|
}), finalize(() => {
|
|
4510
4345
|
this.componentLoaders.delete(route);
|
|
@@ -4547,7 +4382,7 @@ class RouterConfigLoader {
|
|
|
4547
4382
|
rawRoutes = flatten(injector.get(ROUTES, [], InjectFlags.Self | InjectFlags.Optional));
|
|
4548
4383
|
}
|
|
4549
4384
|
const routes = rawRoutes.map(standardizeConfig);
|
|
4550
|
-
NG_DEV_MODE$
|
|
4385
|
+
NG_DEV_MODE$5 && validateConfig(routes, route.path, requireStandaloneComponents);
|
|
4551
4386
|
return { routes, injector };
|
|
4552
4387
|
}), finalize(() => {
|
|
4553
4388
|
this.childrenLoaders.delete(route);
|
|
@@ -4574,9 +4409,9 @@ class RouterConfigLoader {
|
|
|
4574
4409
|
}));
|
|
4575
4410
|
}
|
|
4576
4411
|
}
|
|
4577
|
-
RouterConfigLoader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.
|
|
4578
|
-
RouterConfigLoader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.
|
|
4579
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.
|
|
4412
|
+
RouterConfigLoader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: RouterConfigLoader, deps: [{ token: i0.Injector }, { token: i0.Compiler }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
4413
|
+
RouterConfigLoader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: RouterConfigLoader, providedIn: 'root' });
|
|
4414
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: RouterConfigLoader, decorators: [{
|
|
4580
4415
|
type: Injectable,
|
|
4581
4416
|
args: [{ providedIn: 'root' }]
|
|
4582
4417
|
}], ctorParameters: function () { return [{ type: i0.Injector }, { type: i0.Compiler }]; } });
|
|
@@ -4599,104 +4434,646 @@ function maybeUnwrapDefaultExport(input) {
|
|
|
4599
4434
|
* Use of this source code is governed by an MIT-style license that can be
|
|
4600
4435
|
* found in the LICENSE file at https://angular.io/license
|
|
4601
4436
|
*/
|
|
4602
|
-
|
|
4603
|
-
|
|
4604
|
-
|
|
4605
|
-
|
|
4606
|
-
|
|
4607
|
-
|
|
4608
|
-
|
|
4609
|
-
|
|
4610
|
-
|
|
4611
|
-
|
|
4612
|
-
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
|
|
4616
|
-
|
|
4617
|
-
}
|
|
4618
|
-
extract(url) {
|
|
4619
|
-
return url;
|
|
4620
|
-
}
|
|
4621
|
-
merge(newUrlPart, wholeUrl) {
|
|
4622
|
-
return newUrlPart;
|
|
4623
|
-
}
|
|
4624
|
-
}
|
|
4625
|
-
|
|
4626
|
-
/**
|
|
4627
|
-
* @license
|
|
4628
|
-
* Copyright Google LLC All Rights Reserved.
|
|
4629
|
-
*
|
|
4630
|
-
* Use of this source code is governed by an MIT-style license that can be
|
|
4631
|
-
* found in the LICENSE file at https://angular.io/license
|
|
4632
|
-
*/
|
|
4633
|
-
const NG_DEV_MODE$2 = typeof ngDevMode === 'undefined' || !!ngDevMode;
|
|
4634
|
-
function defaultErrorHandler(error) {
|
|
4635
|
-
throw error;
|
|
4636
|
-
}
|
|
4637
|
-
function defaultMalformedUriErrorHandler(error, urlSerializer, url) {
|
|
4638
|
-
return urlSerializer.parse('/');
|
|
4639
|
-
}
|
|
4640
|
-
/**
|
|
4641
|
-
* The equivalent `IsActiveMatchOptions` options for `Router.isActive` is called with `true`
|
|
4642
|
-
* (exact = true).
|
|
4643
|
-
*/
|
|
4644
|
-
const exactMatchOptions = {
|
|
4645
|
-
paths: 'exact',
|
|
4646
|
-
fragment: 'ignored',
|
|
4647
|
-
matrixParams: 'ignored',
|
|
4648
|
-
queryParams: 'exact'
|
|
4649
|
-
};
|
|
4650
|
-
/**
|
|
4651
|
-
* The equivalent `IsActiveMatchOptions` options for `Router.isActive` is called with `false`
|
|
4652
|
-
* (exact = false).
|
|
4653
|
-
*/
|
|
4654
|
-
const subsetMatchOptions = {
|
|
4655
|
-
paths: 'subset',
|
|
4656
|
-
fragment: 'ignored',
|
|
4657
|
-
matrixParams: 'ignored',
|
|
4658
|
-
queryParams: 'subset'
|
|
4659
|
-
};
|
|
4660
|
-
function assignExtraOptionsToRouter(opts, router) {
|
|
4661
|
-
if (opts.errorHandler) {
|
|
4662
|
-
router.errorHandler = opts.errorHandler;
|
|
4663
|
-
}
|
|
4664
|
-
if (opts.malformedUriErrorHandler) {
|
|
4665
|
-
router.malformedUriErrorHandler = opts.malformedUriErrorHandler;
|
|
4666
|
-
}
|
|
4667
|
-
if (opts.onSameUrlNavigation) {
|
|
4668
|
-
router.onSameUrlNavigation = opts.onSameUrlNavigation;
|
|
4437
|
+
const NG_DEV_MODE$4 = typeof ngDevMode === 'undefined' || !!ngDevMode;
|
|
4438
|
+
class NavigationTransitions {
|
|
4439
|
+
constructor() {
|
|
4440
|
+
this.currentNavigation = null;
|
|
4441
|
+
this.lastSuccessfulNavigation = null;
|
|
4442
|
+
this.events = new Subject();
|
|
4443
|
+
this.configLoader = inject(RouterConfigLoader);
|
|
4444
|
+
this.environmentInjector = inject(EnvironmentInjector);
|
|
4445
|
+
this.urlSerializer = inject(UrlSerializer);
|
|
4446
|
+
this.rootContexts = inject(ChildrenOutletContexts);
|
|
4447
|
+
this.navigationId = 0;
|
|
4448
|
+
const onLoadStart = (r) => this.events.next(new RouteConfigLoadStart(r));
|
|
4449
|
+
const onLoadEnd = (r) => this.events.next(new RouteConfigLoadEnd(r));
|
|
4450
|
+
this.configLoader.onLoadEndListener = onLoadEnd;
|
|
4451
|
+
this.configLoader.onLoadStartListener = onLoadStart;
|
|
4669
4452
|
}
|
|
4670
|
-
|
|
4671
|
-
|
|
4453
|
+
get hasRequestedNavigation() {
|
|
4454
|
+
return this.navigationId !== 0;
|
|
4672
4455
|
}
|
|
4673
|
-
|
|
4674
|
-
|
|
4456
|
+
complete() {
|
|
4457
|
+
this.transitions?.complete();
|
|
4675
4458
|
}
|
|
4676
|
-
|
|
4677
|
-
|
|
4459
|
+
handleNavigationRequest(request) {
|
|
4460
|
+
const id = ++this.navigationId;
|
|
4461
|
+
this.transitions?.next({ ...this.transitions.value, ...request, id });
|
|
4678
4462
|
}
|
|
4679
|
-
|
|
4680
|
-
|
|
4681
|
-
|
|
4682
|
-
|
|
4463
|
+
setupNavigations(router) {
|
|
4464
|
+
this.transitions = new BehaviorSubject({
|
|
4465
|
+
id: 0,
|
|
4466
|
+
targetPageId: 0,
|
|
4467
|
+
currentUrlTree: router.currentUrlTree,
|
|
4468
|
+
currentRawUrl: router.currentUrlTree,
|
|
4469
|
+
extractedUrl: router.urlHandlingStrategy.extract(router.currentUrlTree),
|
|
4470
|
+
urlAfterRedirects: router.urlHandlingStrategy.extract(router.currentUrlTree),
|
|
4471
|
+
rawUrl: router.currentUrlTree,
|
|
4472
|
+
extras: {},
|
|
4473
|
+
resolve: null,
|
|
4474
|
+
reject: null,
|
|
4475
|
+
promise: Promise.resolve(true),
|
|
4476
|
+
source: 'imperative',
|
|
4477
|
+
restoredState: null,
|
|
4478
|
+
currentSnapshot: router.routerState.snapshot,
|
|
4479
|
+
targetSnapshot: null,
|
|
4480
|
+
currentRouterState: router.routerState,
|
|
4481
|
+
targetRouterState: null,
|
|
4482
|
+
guards: { canActivateChecks: [], canDeactivateChecks: [] },
|
|
4483
|
+
guardsResult: null,
|
|
4484
|
+
});
|
|
4485
|
+
return this.transitions.pipe(filter(t => t.id !== 0),
|
|
4486
|
+
// Extract URL
|
|
4487
|
+
map(t => ({ ...t, extractedUrl: router.urlHandlingStrategy.extract(t.rawUrl) })),
|
|
4488
|
+
// Using switchMap so we cancel executing navigations when a new one comes in
|
|
4489
|
+
switchMap(overallTransitionState => {
|
|
4490
|
+
let completed = false;
|
|
4491
|
+
let errored = false;
|
|
4492
|
+
return of(overallTransitionState)
|
|
4493
|
+
.pipe(
|
|
4494
|
+
// Store the Navigation object
|
|
4495
|
+
tap(t => {
|
|
4496
|
+
this.currentNavigation = {
|
|
4497
|
+
id: t.id,
|
|
4498
|
+
initialUrl: t.rawUrl,
|
|
4499
|
+
extractedUrl: t.extractedUrl,
|
|
4500
|
+
trigger: t.source,
|
|
4501
|
+
extras: t.extras,
|
|
4502
|
+
previousNavigation: !this.lastSuccessfulNavigation ? null : {
|
|
4503
|
+
...this.lastSuccessfulNavigation,
|
|
4504
|
+
previousNavigation: null,
|
|
4505
|
+
},
|
|
4506
|
+
};
|
|
4507
|
+
}), switchMap(t => {
|
|
4508
|
+
const browserUrlTree = router.browserUrlTree.toString();
|
|
4509
|
+
const urlTransition = !router.navigated ||
|
|
4510
|
+
t.extractedUrl.toString() !== browserUrlTree ||
|
|
4511
|
+
// Navigations which succeed or ones which fail and are cleaned up
|
|
4512
|
+
// correctly should result in `browserUrlTree` and `currentUrlTree`
|
|
4513
|
+
// matching. If this is not the case, assume something went wrong and
|
|
4514
|
+
// try processing the URL again.
|
|
4515
|
+
browserUrlTree !== router.currentUrlTree.toString();
|
|
4516
|
+
const processCurrentUrl = (router.onSameUrlNavigation === 'reload' ? true : urlTransition) &&
|
|
4517
|
+
router.urlHandlingStrategy.shouldProcessUrl(t.rawUrl);
|
|
4518
|
+
if (processCurrentUrl) {
|
|
4519
|
+
// If the source of the navigation is from a browser event, the URL is
|
|
4520
|
+
// already updated. We already need to sync the internal state.
|
|
4521
|
+
if (isBrowserTriggeredNavigation(t.source)) {
|
|
4522
|
+
router.browserUrlTree = t.extractedUrl;
|
|
4523
|
+
}
|
|
4524
|
+
return of(t).pipe(
|
|
4525
|
+
// Fire NavigationStart event
|
|
4526
|
+
switchMap(t => {
|
|
4527
|
+
const transition = this.transitions?.getValue();
|
|
4528
|
+
this.events.next(new NavigationStart(t.id, this.urlSerializer.serialize(t.extractedUrl), t.source, t.restoredState));
|
|
4529
|
+
if (transition !== this.transitions?.getValue()) {
|
|
4530
|
+
return EMPTY;
|
|
4531
|
+
}
|
|
4532
|
+
// This delay is required to match old behavior that forced
|
|
4533
|
+
// navigation to always be async
|
|
4534
|
+
return Promise.resolve(t);
|
|
4535
|
+
}),
|
|
4536
|
+
// ApplyRedirects
|
|
4537
|
+
applyRedirects(this.environmentInjector, this.configLoader, this.urlSerializer, router.config),
|
|
4538
|
+
// Update the currentNavigation
|
|
4539
|
+
// `urlAfterRedirects` is guaranteed to be set after this point
|
|
4540
|
+
tap(t => {
|
|
4541
|
+
this.currentNavigation = {
|
|
4542
|
+
...this.currentNavigation,
|
|
4543
|
+
finalUrl: t.urlAfterRedirects
|
|
4544
|
+
};
|
|
4545
|
+
overallTransitionState.urlAfterRedirects = t.urlAfterRedirects;
|
|
4546
|
+
}),
|
|
4547
|
+
// Recognize
|
|
4548
|
+
recognize(this.environmentInjector, router.rootComponentType, router.config, this.urlSerializer, router.paramsInheritanceStrategy),
|
|
4549
|
+
// Update URL if in `eager` update mode
|
|
4550
|
+
tap(t => {
|
|
4551
|
+
overallTransitionState.targetSnapshot = t.targetSnapshot;
|
|
4552
|
+
if (router.urlUpdateStrategy === 'eager') {
|
|
4553
|
+
if (!t.extras.skipLocationChange) {
|
|
4554
|
+
const rawUrl = router.urlHandlingStrategy.merge(t.urlAfterRedirects, t.rawUrl);
|
|
4555
|
+
router.setBrowserUrl(rawUrl, t);
|
|
4556
|
+
}
|
|
4557
|
+
router.browserUrlTree = t.urlAfterRedirects;
|
|
4558
|
+
}
|
|
4559
|
+
// Fire RoutesRecognized
|
|
4560
|
+
const routesRecognized = new RoutesRecognized(t.id, this.urlSerializer.serialize(t.extractedUrl), this.urlSerializer.serialize(t.urlAfterRedirects), t.targetSnapshot);
|
|
4561
|
+
this.events.next(routesRecognized);
|
|
4562
|
+
}));
|
|
4563
|
+
}
|
|
4564
|
+
else {
|
|
4565
|
+
const processPreviousUrl = urlTransition && router.rawUrlTree &&
|
|
4566
|
+
router.urlHandlingStrategy.shouldProcessUrl(router.rawUrlTree);
|
|
4567
|
+
/* When the current URL shouldn't be processed, but the previous one
|
|
4568
|
+
* was, we handle this "error condition" by navigating to the
|
|
4569
|
+
* previously successful URL, but leaving the URL intact.*/
|
|
4570
|
+
if (processPreviousUrl) {
|
|
4571
|
+
const { id, extractedUrl, source, restoredState, extras } = t;
|
|
4572
|
+
const navStart = new NavigationStart(id, this.urlSerializer.serialize(extractedUrl), source, restoredState);
|
|
4573
|
+
this.events.next(navStart);
|
|
4574
|
+
const targetSnapshot = createEmptyState(extractedUrl, router.rootComponentType)
|
|
4575
|
+
.snapshot;
|
|
4576
|
+
overallTransitionState = {
|
|
4577
|
+
...t,
|
|
4578
|
+
targetSnapshot,
|
|
4579
|
+
urlAfterRedirects: extractedUrl,
|
|
4580
|
+
extras: { ...extras, skipLocationChange: false, replaceUrl: false },
|
|
4581
|
+
};
|
|
4582
|
+
return of(overallTransitionState);
|
|
4583
|
+
}
|
|
4584
|
+
else {
|
|
4585
|
+
/* When neither the current or previous URL can be processed, do
|
|
4586
|
+
* nothing other than update router's internal reference to the
|
|
4587
|
+
* current "settled" URL. This way the next navigation will be coming
|
|
4588
|
+
* from the current URL in the browser.
|
|
4589
|
+
*/
|
|
4590
|
+
router.rawUrlTree = t.rawUrl;
|
|
4591
|
+
t.resolve(null);
|
|
4592
|
+
return EMPTY;
|
|
4593
|
+
}
|
|
4594
|
+
}
|
|
4595
|
+
}),
|
|
4596
|
+
// --- GUARDS ---
|
|
4597
|
+
tap(t => {
|
|
4598
|
+
const guardsStart = new GuardsCheckStart(t.id, this.urlSerializer.serialize(t.extractedUrl), this.urlSerializer.serialize(t.urlAfterRedirects), t.targetSnapshot);
|
|
4599
|
+
this.events.next(guardsStart);
|
|
4600
|
+
}), map(t => {
|
|
4601
|
+
overallTransitionState = {
|
|
4602
|
+
...t,
|
|
4603
|
+
guards: getAllRouteGuards(t.targetSnapshot, t.currentSnapshot, this.rootContexts)
|
|
4604
|
+
};
|
|
4605
|
+
return overallTransitionState;
|
|
4606
|
+
}), checkGuards(this.environmentInjector, (evt) => this.events.next(evt)), tap(t => {
|
|
4607
|
+
overallTransitionState.guardsResult = t.guardsResult;
|
|
4608
|
+
if (isUrlTree(t.guardsResult)) {
|
|
4609
|
+
throw redirectingNavigationError(this.urlSerializer, t.guardsResult);
|
|
4610
|
+
}
|
|
4611
|
+
const guardsEnd = new GuardsCheckEnd(t.id, this.urlSerializer.serialize(t.extractedUrl), this.urlSerializer.serialize(t.urlAfterRedirects), t.targetSnapshot, !!t.guardsResult);
|
|
4612
|
+
this.events.next(guardsEnd);
|
|
4613
|
+
}), filter(t => {
|
|
4614
|
+
if (!t.guardsResult) {
|
|
4615
|
+
router.restoreHistory(t);
|
|
4616
|
+
this.cancelNavigationTransition(t, '', 3 /* NavigationCancellationCode.GuardRejected */, router);
|
|
4617
|
+
return false;
|
|
4618
|
+
}
|
|
4619
|
+
return true;
|
|
4620
|
+
}),
|
|
4621
|
+
// --- RESOLVE ---
|
|
4622
|
+
switchTap(t => {
|
|
4623
|
+
if (t.guards.canActivateChecks.length) {
|
|
4624
|
+
return of(t).pipe(tap(t => {
|
|
4625
|
+
const resolveStart = new ResolveStart(t.id, this.urlSerializer.serialize(t.extractedUrl), this.urlSerializer.serialize(t.urlAfterRedirects), t.targetSnapshot);
|
|
4626
|
+
this.events.next(resolveStart);
|
|
4627
|
+
}), switchMap(t => {
|
|
4628
|
+
let dataResolved = false;
|
|
4629
|
+
return of(t).pipe(resolveData(router.paramsInheritanceStrategy, this.environmentInjector), tap({
|
|
4630
|
+
next: () => dataResolved = true,
|
|
4631
|
+
complete: () => {
|
|
4632
|
+
if (!dataResolved) {
|
|
4633
|
+
router.restoreHistory(t);
|
|
4634
|
+
this.cancelNavigationTransition(t, NG_DEV_MODE$4 ?
|
|
4635
|
+
`At least one route resolver didn't emit any value.` :
|
|
4636
|
+
'', 2 /* NavigationCancellationCode.NoDataFromResolver */, router);
|
|
4637
|
+
}
|
|
4638
|
+
}
|
|
4639
|
+
}));
|
|
4640
|
+
}), tap(t => {
|
|
4641
|
+
const resolveEnd = new ResolveEnd(t.id, this.urlSerializer.serialize(t.extractedUrl), this.urlSerializer.serialize(t.urlAfterRedirects), t.targetSnapshot);
|
|
4642
|
+
this.events.next(resolveEnd);
|
|
4643
|
+
}));
|
|
4644
|
+
}
|
|
4645
|
+
return undefined;
|
|
4646
|
+
}),
|
|
4647
|
+
// --- LOAD COMPONENTS ---
|
|
4648
|
+
switchTap((t) => {
|
|
4649
|
+
const loadComponents = (route) => {
|
|
4650
|
+
const loaders = [];
|
|
4651
|
+
if (route.routeConfig?.loadComponent &&
|
|
4652
|
+
!route.routeConfig._loadedComponent) {
|
|
4653
|
+
loaders.push(this.configLoader.loadComponent(route.routeConfig)
|
|
4654
|
+
.pipe(tap(loadedComponent => {
|
|
4655
|
+
route.component = loadedComponent;
|
|
4656
|
+
}), map(() => void 0)));
|
|
4657
|
+
}
|
|
4658
|
+
for (const child of route.children) {
|
|
4659
|
+
loaders.push(...loadComponents(child));
|
|
4660
|
+
}
|
|
4661
|
+
return loaders;
|
|
4662
|
+
};
|
|
4663
|
+
return combineLatest(loadComponents(t.targetSnapshot.root))
|
|
4664
|
+
.pipe(defaultIfEmpty(), take(1));
|
|
4665
|
+
}), switchTap(() => router.afterPreactivation()), map((t) => {
|
|
4666
|
+
const targetRouterState = createRouterState(router.routeReuseStrategy, t.targetSnapshot, t.currentRouterState);
|
|
4667
|
+
overallTransitionState = { ...t, targetRouterState };
|
|
4668
|
+
return (overallTransitionState);
|
|
4669
|
+
}),
|
|
4670
|
+
/* Once here, we are about to activate synchronously. The assumption is
|
|
4671
|
+
this will succeed, and user code may read from the Router service.
|
|
4672
|
+
Therefore before activation, we need to update router properties storing
|
|
4673
|
+
the current URL and the RouterState, as well as updated the browser URL.
|
|
4674
|
+
All this should happen *before* activating. */
|
|
4675
|
+
tap((t) => {
|
|
4676
|
+
router.currentUrlTree = t.urlAfterRedirects;
|
|
4677
|
+
router.rawUrlTree =
|
|
4678
|
+
router.urlHandlingStrategy.merge(t.urlAfterRedirects, t.rawUrl);
|
|
4679
|
+
router.routerState =
|
|
4680
|
+
t.targetRouterState;
|
|
4681
|
+
if (router.urlUpdateStrategy === 'deferred') {
|
|
4682
|
+
if (!t.extras.skipLocationChange) {
|
|
4683
|
+
router.setBrowserUrl(router.rawUrlTree, t);
|
|
4684
|
+
}
|
|
4685
|
+
router.browserUrlTree = t.urlAfterRedirects;
|
|
4686
|
+
}
|
|
4687
|
+
}), activateRoutes(this.rootContexts, router.routeReuseStrategy, (evt) => this.events.next(evt)), tap({
|
|
4688
|
+
next: (t) => {
|
|
4689
|
+
completed = true;
|
|
4690
|
+
this.lastSuccessfulNavigation = this.currentNavigation;
|
|
4691
|
+
router.navigated = true;
|
|
4692
|
+
this.events.next(new NavigationEnd(t.id, this.urlSerializer.serialize(t.extractedUrl), this.urlSerializer.serialize(router.currentUrlTree)));
|
|
4693
|
+
router.titleStrategy?.updateTitle(t.targetRouterState.snapshot);
|
|
4694
|
+
t.resolve(true);
|
|
4695
|
+
},
|
|
4696
|
+
complete: () => {
|
|
4697
|
+
completed = true;
|
|
4698
|
+
}
|
|
4699
|
+
}), finalize(() => {
|
|
4700
|
+
/* When the navigation stream finishes either through error or success,
|
|
4701
|
+
* we set the `completed` or `errored` flag. However, there are some
|
|
4702
|
+
* situations where we could get here without either of those being set.
|
|
4703
|
+
* For instance, a redirect during NavigationStart. Therefore, this is a
|
|
4704
|
+
* catch-all to make sure the NavigationCancel event is fired when a
|
|
4705
|
+
* navigation gets cancelled but not caught by other means. */
|
|
4706
|
+
if (!completed && !errored) {
|
|
4707
|
+
const cancelationReason = NG_DEV_MODE$4 ?
|
|
4708
|
+
`Navigation ID ${overallTransitionState
|
|
4709
|
+
.id} is not equal to the current navigation id ${this.navigationId}` :
|
|
4710
|
+
'';
|
|
4711
|
+
this.cancelNavigationTransition(overallTransitionState, cancelationReason, 1 /* NavigationCancellationCode.SupersededByNewNavigation */, router);
|
|
4712
|
+
}
|
|
4713
|
+
// Only clear current navigation if it is still set to the one that
|
|
4714
|
+
// finalized.
|
|
4715
|
+
if (this.currentNavigation?.id === overallTransitionState.id) {
|
|
4716
|
+
this.currentNavigation = null;
|
|
4717
|
+
}
|
|
4718
|
+
}), catchError((e) => {
|
|
4719
|
+
errored = true;
|
|
4720
|
+
/* This error type is issued during Redirect, and is handled as a
|
|
4721
|
+
* cancellation rather than an error. */
|
|
4722
|
+
if (isNavigationCancelingError$1(e)) {
|
|
4723
|
+
if (!isRedirectingNavigationCancelingError$1(e)) {
|
|
4724
|
+
// Set property only if we're not redirecting. If we landed on a page
|
|
4725
|
+
// and redirect to `/` route, the new navigation is going to see the
|
|
4726
|
+
// `/` isn't a change from the default currentUrlTree and won't
|
|
4727
|
+
// navigate. This is only applicable with initial navigation, so
|
|
4728
|
+
// setting `navigated` only when not redirecting resolves this
|
|
4729
|
+
// scenario.
|
|
4730
|
+
router.navigated = true;
|
|
4731
|
+
router.restoreHistory(overallTransitionState, true);
|
|
4732
|
+
}
|
|
4733
|
+
const navCancel = new NavigationCancel(overallTransitionState.id, this.urlSerializer.serialize(overallTransitionState.extractedUrl), e.message, e.cancellationCode);
|
|
4734
|
+
this.events.next(navCancel);
|
|
4735
|
+
// When redirecting, we need to delay resolving the navigation
|
|
4736
|
+
// promise and push it to the redirect navigation
|
|
4737
|
+
if (!isRedirectingNavigationCancelingError$1(e)) {
|
|
4738
|
+
overallTransitionState.resolve(false);
|
|
4739
|
+
}
|
|
4740
|
+
else {
|
|
4741
|
+
const mergedTree = router.urlHandlingStrategy.merge(e.url, router.rawUrlTree);
|
|
4742
|
+
const extras = {
|
|
4743
|
+
skipLocationChange: overallTransitionState.extras.skipLocationChange,
|
|
4744
|
+
// The URL is already updated at this point if we have 'eager' URL
|
|
4745
|
+
// updates or if the navigation was triggered by the browser (back
|
|
4746
|
+
// button, URL bar, etc). We want to replace that item in history
|
|
4747
|
+
// if the navigation is rejected.
|
|
4748
|
+
replaceUrl: router.urlUpdateStrategy === 'eager' ||
|
|
4749
|
+
isBrowserTriggeredNavigation(overallTransitionState.source)
|
|
4750
|
+
};
|
|
4751
|
+
router.scheduleNavigation(mergedTree, 'imperative', null, extras, {
|
|
4752
|
+
resolve: overallTransitionState.resolve,
|
|
4753
|
+
reject: overallTransitionState.reject,
|
|
4754
|
+
promise: overallTransitionState.promise
|
|
4755
|
+
});
|
|
4756
|
+
}
|
|
4757
|
+
/* All other errors should reset to the router's internal URL reference
|
|
4758
|
+
* to the pre-error state. */
|
|
4759
|
+
}
|
|
4760
|
+
else {
|
|
4761
|
+
router.restoreHistory(overallTransitionState, true);
|
|
4762
|
+
const navError = new NavigationError(overallTransitionState.id, this.urlSerializer.serialize(overallTransitionState.extractedUrl), e, overallTransitionState.targetSnapshot ?? undefined);
|
|
4763
|
+
this.events.next(navError);
|
|
4764
|
+
try {
|
|
4765
|
+
overallTransitionState.resolve(router.errorHandler(e));
|
|
4766
|
+
}
|
|
4767
|
+
catch (ee) {
|
|
4768
|
+
overallTransitionState.reject(ee);
|
|
4769
|
+
}
|
|
4770
|
+
}
|
|
4771
|
+
return EMPTY;
|
|
4772
|
+
}));
|
|
4773
|
+
// TODO(jasonaden): remove cast once g3 is on updated TypeScript
|
|
4774
|
+
}));
|
|
4775
|
+
}
|
|
4776
|
+
cancelNavigationTransition(t, reason, code, router) {
|
|
4777
|
+
const navCancel = new NavigationCancel(t.id, this.urlSerializer.serialize(t.extractedUrl), reason, code);
|
|
4778
|
+
this.events.next(navCancel);
|
|
4779
|
+
t.resolve(false);
|
|
4780
|
+
}
|
|
4781
|
+
}
|
|
4782
|
+
NavigationTransitions.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: NavigationTransitions, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
4783
|
+
NavigationTransitions.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: NavigationTransitions, providedIn: 'root' });
|
|
4784
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: NavigationTransitions, decorators: [{
|
|
4785
|
+
type: Injectable,
|
|
4786
|
+
args: [{ providedIn: 'root' }]
|
|
4787
|
+
}], ctorParameters: function () { return []; } });
|
|
4788
|
+
function isBrowserTriggeredNavigation(source) {
|
|
4789
|
+
return source !== 'imperative';
|
|
4790
|
+
}
|
|
4791
|
+
|
|
4792
|
+
/**
|
|
4793
|
+
* @license
|
|
4794
|
+
* Copyright Google LLC All Rights Reserved.
|
|
4795
|
+
*
|
|
4796
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
4797
|
+
* found in the LICENSE file at https://angular.io/license
|
|
4798
|
+
*/
|
|
4799
|
+
/**
|
|
4800
|
+
* Provides a strategy for setting the page title after a router navigation.
|
|
4801
|
+
*
|
|
4802
|
+
* The built-in implementation traverses the router state snapshot and finds the deepest primary
|
|
4803
|
+
* outlet with `title` property. Given the `Routes` below, navigating to
|
|
4804
|
+
* `/base/child(popup:aux)` would result in the document title being set to "child".
|
|
4805
|
+
* ```
|
|
4806
|
+
* [
|
|
4807
|
+
* {path: 'base', title: 'base', children: [
|
|
4808
|
+
* {path: 'child', title: 'child'},
|
|
4809
|
+
* ],
|
|
4810
|
+
* {path: 'aux', outlet: 'popup', title: 'popupTitle'}
|
|
4811
|
+
* ]
|
|
4812
|
+
* ```
|
|
4813
|
+
*
|
|
4814
|
+
* This class can be used as a base class for custom title strategies. That is, you can create your
|
|
4815
|
+
* own class that extends the `TitleStrategy`. Note that in the above example, the `title`
|
|
4816
|
+
* from the named outlet is never used. However, a custom strategy might be implemented to
|
|
4817
|
+
* incorporate titles in named outlets.
|
|
4818
|
+
*
|
|
4819
|
+
* @publicApi
|
|
4820
|
+
* @see [Page title guide](guide/router#setting-the-page-title)
|
|
4821
|
+
*/
|
|
4822
|
+
class TitleStrategy {
|
|
4823
|
+
/**
|
|
4824
|
+
* @returns The `title` of the deepest primary route.
|
|
4825
|
+
*/
|
|
4826
|
+
buildTitle(snapshot) {
|
|
4827
|
+
let pageTitle;
|
|
4828
|
+
let route = snapshot.root;
|
|
4829
|
+
while (route !== undefined) {
|
|
4830
|
+
pageTitle = this.getResolvedTitleForRoute(route) ?? pageTitle;
|
|
4831
|
+
route = route.children.find(child => child.outlet === PRIMARY_OUTLET);
|
|
4832
|
+
}
|
|
4833
|
+
return pageTitle;
|
|
4834
|
+
}
|
|
4835
|
+
/**
|
|
4836
|
+
* Given an `ActivatedRouteSnapshot`, returns the final value of the
|
|
4837
|
+
* `Route.title` property, which can either be a static string or a resolved value.
|
|
4838
|
+
*/
|
|
4839
|
+
getResolvedTitleForRoute(snapshot) {
|
|
4840
|
+
return snapshot.data[RouteTitleKey];
|
|
4841
|
+
}
|
|
4842
|
+
}
|
|
4843
|
+
TitleStrategy.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: TitleStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
4844
|
+
TitleStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: TitleStrategy, providedIn: 'root', useFactory: () => inject(DefaultTitleStrategy) });
|
|
4845
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: TitleStrategy, decorators: [{
|
|
4846
|
+
type: Injectable,
|
|
4847
|
+
args: [{ providedIn: 'root', useFactory: () => inject(DefaultTitleStrategy) }]
|
|
4848
|
+
}] });
|
|
4849
|
+
/**
|
|
4850
|
+
* The default `TitleStrategy` used by the router that updates the title using the `Title` service.
|
|
4851
|
+
*/
|
|
4852
|
+
class DefaultTitleStrategy extends TitleStrategy {
|
|
4853
|
+
constructor(title) {
|
|
4854
|
+
super();
|
|
4855
|
+
this.title = title;
|
|
4856
|
+
}
|
|
4857
|
+
/**
|
|
4858
|
+
* Sets the title of the browser to the given value.
|
|
4859
|
+
*
|
|
4860
|
+
* @param title The `pageTitle` from the deepest primary route.
|
|
4861
|
+
*/
|
|
4862
|
+
updateTitle(snapshot) {
|
|
4863
|
+
const title = this.buildTitle(snapshot);
|
|
4864
|
+
if (title !== undefined) {
|
|
4865
|
+
this.title.setTitle(title);
|
|
4866
|
+
}
|
|
4867
|
+
}
|
|
4868
|
+
}
|
|
4869
|
+
DefaultTitleStrategy.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: DefaultTitleStrategy, deps: [{ token: i1.Title }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
4870
|
+
DefaultTitleStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: DefaultTitleStrategy, providedIn: 'root' });
|
|
4871
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: DefaultTitleStrategy, decorators: [{
|
|
4872
|
+
type: Injectable,
|
|
4873
|
+
args: [{ providedIn: 'root' }]
|
|
4874
|
+
}], ctorParameters: function () { return [{ type: i1.Title }]; } });
|
|
4875
|
+
|
|
4876
|
+
/**
|
|
4877
|
+
* @license
|
|
4878
|
+
* Copyright Google LLC All Rights Reserved.
|
|
4879
|
+
*
|
|
4880
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
4881
|
+
* found in the LICENSE file at https://angular.io/license
|
|
4882
|
+
*/
|
|
4883
|
+
/**
|
|
4884
|
+
* @description
|
|
4885
|
+
*
|
|
4886
|
+
* Provides a way to customize when activated routes get reused.
|
|
4887
|
+
*
|
|
4888
|
+
* @publicApi
|
|
4889
|
+
*/
|
|
4890
|
+
class RouteReuseStrategy {
|
|
4891
|
+
}
|
|
4892
|
+
RouteReuseStrategy.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: RouteReuseStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
4893
|
+
RouteReuseStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: RouteReuseStrategy, providedIn: 'root', useFactory: () => inject(DefaultRouteReuseStrategy) });
|
|
4894
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: RouteReuseStrategy, decorators: [{
|
|
4895
|
+
type: Injectable,
|
|
4896
|
+
args: [{ providedIn: 'root', useFactory: () => inject(DefaultRouteReuseStrategy) }]
|
|
4897
|
+
}] });
|
|
4898
|
+
/**
|
|
4899
|
+
* @description
|
|
4900
|
+
*
|
|
4901
|
+
* This base route reuse strategy only reuses routes when the matched router configs are
|
|
4902
|
+
* identical. This prevents components from being destroyed and recreated
|
|
4903
|
+
* when just the route parameters, query parameters or fragment change
|
|
4904
|
+
* (that is, the existing component is _reused_).
|
|
4905
|
+
*
|
|
4906
|
+
* This strategy does not store any routes for later reuse.
|
|
4907
|
+
*
|
|
4908
|
+
* Angular uses this strategy by default.
|
|
4909
|
+
*
|
|
4910
|
+
*
|
|
4911
|
+
* It can be used as a base class for custom route reuse strategies, i.e. you can create your own
|
|
4912
|
+
* class that extends the `BaseRouteReuseStrategy` one.
|
|
4913
|
+
* @publicApi
|
|
4914
|
+
*/
|
|
4915
|
+
class BaseRouteReuseStrategy {
|
|
4916
|
+
/**
|
|
4917
|
+
* Whether the given route should detach for later reuse.
|
|
4918
|
+
* Always returns false for `BaseRouteReuseStrategy`.
|
|
4919
|
+
* */
|
|
4920
|
+
shouldDetach(route) {
|
|
4921
|
+
return false;
|
|
4922
|
+
}
|
|
4923
|
+
/**
|
|
4924
|
+
* A no-op; the route is never stored since this strategy never detaches routes for later re-use.
|
|
4925
|
+
*/
|
|
4926
|
+
store(route, detachedTree) { }
|
|
4927
|
+
/** Returns `false`, meaning the route (and its subtree) is never reattached */
|
|
4928
|
+
shouldAttach(route) {
|
|
4929
|
+
return false;
|
|
4930
|
+
}
|
|
4931
|
+
/** Returns `null` because this strategy does not store routes for later re-use. */
|
|
4932
|
+
retrieve(route) {
|
|
4933
|
+
return null;
|
|
4934
|
+
}
|
|
4935
|
+
/**
|
|
4936
|
+
* Determines if a route should be reused.
|
|
4937
|
+
* This strategy returns `true` when the future route config and current route config are
|
|
4938
|
+
* identical.
|
|
4939
|
+
*/
|
|
4940
|
+
shouldReuseRoute(future, curr) {
|
|
4941
|
+
return future.routeConfig === curr.routeConfig;
|
|
4942
|
+
}
|
|
4943
|
+
}
|
|
4944
|
+
class DefaultRouteReuseStrategy extends BaseRouteReuseStrategy {
|
|
4945
|
+
}
|
|
4946
|
+
DefaultRouteReuseStrategy.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: DefaultRouteReuseStrategy, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
|
|
4947
|
+
DefaultRouteReuseStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: DefaultRouteReuseStrategy, providedIn: 'root' });
|
|
4948
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: DefaultRouteReuseStrategy, decorators: [{
|
|
4949
|
+
type: Injectable,
|
|
4950
|
+
args: [{ providedIn: 'root' }]
|
|
4951
|
+
}] });
|
|
4952
|
+
|
|
4953
|
+
/**
|
|
4954
|
+
* @license
|
|
4955
|
+
* Copyright Google LLC All Rights Reserved.
|
|
4956
|
+
*
|
|
4957
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
4958
|
+
* found in the LICENSE file at https://angular.io/license
|
|
4959
|
+
*/
|
|
4960
|
+
const NG_DEV_MODE$3 = typeof ngDevMode === 'undefined' || !!ngDevMode;
|
|
4961
|
+
/**
|
|
4962
|
+
* A [DI token](guide/glossary/#di-token) for the router service.
|
|
4963
|
+
*
|
|
4964
|
+
* @publicApi
|
|
4965
|
+
*/
|
|
4966
|
+
const ROUTER_CONFIGURATION = new InjectionToken(NG_DEV_MODE$3 ? 'router config' : '', {
|
|
4967
|
+
providedIn: 'root',
|
|
4968
|
+
factory: () => ({}),
|
|
4969
|
+
});
|
|
4970
|
+
|
|
4971
|
+
/**
|
|
4972
|
+
* @license
|
|
4973
|
+
* Copyright Google LLC All Rights Reserved.
|
|
4974
|
+
*
|
|
4975
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
4976
|
+
* found in the LICENSE file at https://angular.io/license
|
|
4977
|
+
*/
|
|
4978
|
+
/**
|
|
4979
|
+
* @description
|
|
4980
|
+
*
|
|
4981
|
+
* Provides a way to migrate AngularJS applications to Angular.
|
|
4982
|
+
*
|
|
4983
|
+
* @publicApi
|
|
4984
|
+
*/
|
|
4985
|
+
class UrlHandlingStrategy {
|
|
4986
|
+
}
|
|
4987
|
+
UrlHandlingStrategy.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: UrlHandlingStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
4988
|
+
UrlHandlingStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: UrlHandlingStrategy, providedIn: 'root', useFactory: () => inject(DefaultUrlHandlingStrategy) });
|
|
4989
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: UrlHandlingStrategy, decorators: [{
|
|
4990
|
+
type: Injectable,
|
|
4991
|
+
args: [{ providedIn: 'root', useFactory: () => inject(DefaultUrlHandlingStrategy) }]
|
|
4992
|
+
}] });
|
|
4993
|
+
/**
|
|
4994
|
+
* @publicApi
|
|
4995
|
+
*/
|
|
4996
|
+
class DefaultUrlHandlingStrategy {
|
|
4997
|
+
shouldProcessUrl(url) {
|
|
4998
|
+
return true;
|
|
4999
|
+
}
|
|
5000
|
+
extract(url) {
|
|
5001
|
+
return url;
|
|
5002
|
+
}
|
|
5003
|
+
merge(newUrlPart, wholeUrl) {
|
|
5004
|
+
return newUrlPart;
|
|
5005
|
+
}
|
|
5006
|
+
}
|
|
5007
|
+
DefaultUrlHandlingStrategy.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: DefaultUrlHandlingStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
5008
|
+
DefaultUrlHandlingStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: DefaultUrlHandlingStrategy, providedIn: 'root' });
|
|
5009
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: DefaultUrlHandlingStrategy, decorators: [{
|
|
5010
|
+
type: Injectable,
|
|
5011
|
+
args: [{ providedIn: 'root' }]
|
|
5012
|
+
}] });
|
|
5013
|
+
|
|
5014
|
+
/**
|
|
5015
|
+
* @license
|
|
5016
|
+
* Copyright Google LLC All Rights Reserved.
|
|
5017
|
+
*
|
|
5018
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
5019
|
+
* found in the LICENSE file at https://angular.io/license
|
|
5020
|
+
*/
|
|
5021
|
+
const NG_DEV_MODE$2 = typeof ngDevMode === 'undefined' || !!ngDevMode;
|
|
5022
|
+
function defaultErrorHandler(error) {
|
|
5023
|
+
throw error;
|
|
5024
|
+
}
|
|
5025
|
+
function defaultMalformedUriErrorHandler(error, urlSerializer, url) {
|
|
5026
|
+
return urlSerializer.parse('/');
|
|
5027
|
+
}
|
|
5028
|
+
/**
|
|
5029
|
+
* The equivalent `IsActiveMatchOptions` options for `Router.isActive` is called with `true`
|
|
5030
|
+
* (exact = true).
|
|
5031
|
+
*/
|
|
5032
|
+
const exactMatchOptions = {
|
|
5033
|
+
paths: 'exact',
|
|
5034
|
+
fragment: 'ignored',
|
|
5035
|
+
matrixParams: 'ignored',
|
|
5036
|
+
queryParams: 'exact'
|
|
5037
|
+
};
|
|
5038
|
+
/**
|
|
5039
|
+
* The equivalent `IsActiveMatchOptions` options for `Router.isActive` is called with `false`
|
|
5040
|
+
* (exact = false).
|
|
5041
|
+
*/
|
|
5042
|
+
const subsetMatchOptions = {
|
|
5043
|
+
paths: 'subset',
|
|
5044
|
+
fragment: 'ignored',
|
|
5045
|
+
matrixParams: 'ignored',
|
|
5046
|
+
queryParams: 'subset'
|
|
5047
|
+
};
|
|
5048
|
+
function assignExtraOptionsToRouter(opts, router) {
|
|
5049
|
+
if (opts.errorHandler) {
|
|
5050
|
+
router.errorHandler = opts.errorHandler;
|
|
5051
|
+
}
|
|
5052
|
+
if (opts.malformedUriErrorHandler) {
|
|
5053
|
+
router.malformedUriErrorHandler = opts.malformedUriErrorHandler;
|
|
5054
|
+
}
|
|
5055
|
+
if (opts.onSameUrlNavigation) {
|
|
5056
|
+
router.onSameUrlNavigation = opts.onSameUrlNavigation;
|
|
5057
|
+
}
|
|
5058
|
+
if (opts.paramsInheritanceStrategy) {
|
|
5059
|
+
router.paramsInheritanceStrategy = opts.paramsInheritanceStrategy;
|
|
5060
|
+
}
|
|
5061
|
+
if (opts.urlUpdateStrategy) {
|
|
5062
|
+
router.urlUpdateStrategy = opts.urlUpdateStrategy;
|
|
5063
|
+
}
|
|
5064
|
+
if (opts.canceledNavigationResolution) {
|
|
5065
|
+
router.canceledNavigationResolution = opts.canceledNavigationResolution;
|
|
5066
|
+
}
|
|
5067
|
+
}
|
|
5068
|
+
function setupRouter() {
|
|
5069
|
+
const urlSerializer = inject(UrlSerializer);
|
|
5070
|
+
const contexts = inject(ChildrenOutletContexts);
|
|
4683
5071
|
const location = inject(Location);
|
|
4684
5072
|
const injector = inject(Injector);
|
|
4685
5073
|
const compiler = inject(Compiler);
|
|
4686
5074
|
const config = inject(ROUTES, { optional: true }) ?? [];
|
|
4687
5075
|
const opts = inject(ROUTER_CONFIGURATION, { optional: true }) ?? {};
|
|
4688
|
-
const defaultTitleStrategy = inject(DefaultTitleStrategy);
|
|
4689
|
-
const titleStrategy = inject(TitleStrategy, { optional: true });
|
|
4690
|
-
const urlHandlingStrategy = inject(UrlHandlingStrategy, { optional: true });
|
|
4691
|
-
const routeReuseStrategy = inject(RouteReuseStrategy, { optional: true });
|
|
4692
5076
|
const router = new Router(null, urlSerializer, contexts, location, injector, compiler, flatten(config));
|
|
4693
|
-
if (urlHandlingStrategy) {
|
|
4694
|
-
router.urlHandlingStrategy = urlHandlingStrategy;
|
|
4695
|
-
}
|
|
4696
|
-
if (routeReuseStrategy) {
|
|
4697
|
-
router.routeReuseStrategy = routeReuseStrategy;
|
|
4698
|
-
}
|
|
4699
|
-
router.titleStrategy = titleStrategy ?? defaultTitleStrategy;
|
|
4700
5077
|
assignExtraOptionsToRouter(opts, router);
|
|
4701
5078
|
return router;
|
|
4702
5079
|
}
|
|
@@ -4717,16 +5094,15 @@ class Router {
|
|
|
4717
5094
|
* Creates the router service.
|
|
4718
5095
|
*/
|
|
4719
5096
|
// TODO: vsavkin make internal after the final is out.
|
|
4720
|
-
constructor(
|
|
5097
|
+
constructor(
|
|
5098
|
+
/** @internal */
|
|
5099
|
+
rootComponentType, urlSerializer, rootContexts, location, injector, compiler, config) {
|
|
4721
5100
|
this.rootComponentType = rootComponentType;
|
|
4722
5101
|
this.urlSerializer = urlSerializer;
|
|
4723
5102
|
this.rootContexts = rootContexts;
|
|
4724
5103
|
this.location = location;
|
|
4725
5104
|
this.config = config;
|
|
4726
|
-
this.lastSuccessfulNavigation = null;
|
|
4727
|
-
this.currentNavigation = null;
|
|
4728
5105
|
this.disposed = false;
|
|
4729
|
-
this.navigationId = 0;
|
|
4730
5106
|
/**
|
|
4731
5107
|
* The id of the currently active page in the router.
|
|
4732
5108
|
* Updated to the transition's target id on a successful navigation.
|
|
@@ -4737,10 +5113,6 @@ class Router {
|
|
|
4737
5113
|
*/
|
|
4738
5114
|
this.currentPageId = 0;
|
|
4739
5115
|
this.isNgZoneEnabled = false;
|
|
4740
|
-
/**
|
|
4741
|
-
* An event stream for routing events in this NgModule.
|
|
4742
|
-
*/
|
|
4743
|
-
this.events = new Subject();
|
|
4744
5116
|
/**
|
|
4745
5117
|
* A handler for navigation errors in this NgModule.
|
|
4746
5118
|
*/
|
|
@@ -4769,11 +5141,15 @@ class Router {
|
|
|
4769
5141
|
* A strategy for extracting and merging URLs.
|
|
4770
5142
|
* Used for AngularJS to Angular migrations.
|
|
4771
5143
|
*/
|
|
4772
|
-
this.urlHandlingStrategy =
|
|
5144
|
+
this.urlHandlingStrategy = inject(UrlHandlingStrategy);
|
|
4773
5145
|
/**
|
|
4774
5146
|
* A strategy for re-using routes.
|
|
4775
5147
|
*/
|
|
4776
|
-
this.routeReuseStrategy =
|
|
5148
|
+
this.routeReuseStrategy = inject(RouteReuseStrategy);
|
|
5149
|
+
/**
|
|
5150
|
+
* A strategy for setting the title based on the `routerState`.
|
|
5151
|
+
*/
|
|
5152
|
+
this.titleStrategy = inject(TitleStrategy);
|
|
4777
5153
|
/**
|
|
4778
5154
|
* How to handle a navigation request to the current URL. One of:
|
|
4779
5155
|
*
|
|
@@ -4829,43 +5205,26 @@ class Router {
|
|
|
4829
5205
|
*
|
|
4830
5206
|
*/
|
|
4831
5207
|
this.canceledNavigationResolution = 'replace';
|
|
4832
|
-
|
|
4833
|
-
const onLoadEnd = (r) => this.triggerEvent(new RouteConfigLoadEnd(r));
|
|
4834
|
-
this.configLoader = injector.get(RouterConfigLoader);
|
|
4835
|
-
this.configLoader.onLoadEndListener = onLoadEnd;
|
|
4836
|
-
this.configLoader.onLoadStartListener = onLoadStart;
|
|
4837
|
-
this.ngModule = injector.get(NgModuleRef);
|
|
5208
|
+
this.navigationTransitions = inject(NavigationTransitions);
|
|
4838
5209
|
this.console = injector.get(ɵConsole);
|
|
4839
5210
|
const ngZone = injector.get(NgZone);
|
|
4840
|
-
this.isNgZoneEnabled = ngZone instanceof NgZone && NgZone.isInAngularZone();
|
|
4841
|
-
this.resetConfig(config);
|
|
4842
|
-
this.currentUrlTree = new UrlTree();
|
|
4843
|
-
this.rawUrlTree = this.currentUrlTree;
|
|
4844
|
-
this.browserUrlTree = this.currentUrlTree;
|
|
4845
|
-
this.routerState = createEmptyState(this.currentUrlTree, this.rootComponentType);
|
|
4846
|
-
this.
|
|
4847
|
-
id
|
|
4848
|
-
targetPageId
|
|
4849
|
-
|
|
4850
|
-
|
|
4851
|
-
extractedUrl: this.urlHandlingStrategy.extract(this.currentUrlTree),
|
|
4852
|
-
urlAfterRedirects: this.urlHandlingStrategy.extract(this.currentUrlTree),
|
|
4853
|
-
rawUrl: this.currentUrlTree,
|
|
4854
|
-
extras: {},
|
|
4855
|
-
resolve: null,
|
|
4856
|
-
reject: null,
|
|
4857
|
-
promise: Promise.resolve(true),
|
|
4858
|
-
source: 'imperative',
|
|
4859
|
-
restoredState: null,
|
|
4860
|
-
currentSnapshot: this.routerState.snapshot,
|
|
4861
|
-
targetSnapshot: null,
|
|
4862
|
-
currentRouterState: this.routerState,
|
|
4863
|
-
targetRouterState: null,
|
|
4864
|
-
guards: { canActivateChecks: [], canDeactivateChecks: [] },
|
|
4865
|
-
guardsResult: null,
|
|
5211
|
+
this.isNgZoneEnabled = ngZone instanceof NgZone && NgZone.isInAngularZone();
|
|
5212
|
+
this.resetConfig(config);
|
|
5213
|
+
this.currentUrlTree = new UrlTree();
|
|
5214
|
+
this.rawUrlTree = this.currentUrlTree;
|
|
5215
|
+
this.browserUrlTree = this.currentUrlTree;
|
|
5216
|
+
this.routerState = createEmptyState(this.currentUrlTree, this.rootComponentType);
|
|
5217
|
+
this.navigationTransitions.setupNavigations(this).subscribe(t => {
|
|
5218
|
+
this.lastSuccessfulId = t.id;
|
|
5219
|
+
this.currentPageId = t.targetPageId;
|
|
5220
|
+
}, e => {
|
|
5221
|
+
this.console.warn(`Unhandled Navigation Error: ${e}`);
|
|
4866
5222
|
});
|
|
4867
|
-
|
|
4868
|
-
|
|
5223
|
+
}
|
|
5224
|
+
// TODO(b/260747083): This should not exist and navigationId should be private in
|
|
5225
|
+
// `NavigationTransitions`
|
|
5226
|
+
get navigationId() {
|
|
5227
|
+
return this.navigationTransitions.navigationId;
|
|
4869
5228
|
}
|
|
4870
5229
|
/**
|
|
4871
5230
|
* The ɵrouterPageId of whatever page is currently active in the browser history. This is
|
|
@@ -4875,290 +5234,15 @@ class Router {
|
|
|
4875
5234
|
get browserPageId() {
|
|
4876
5235
|
return this.location.getState()?.ɵrouterPageId;
|
|
4877
5236
|
}
|
|
4878
|
-
|
|
4879
|
-
|
|
4880
|
-
|
|
4881
|
-
|
|
4882
|
-
|
|
4883
|
-
//
|
|
4884
|
-
|
|
4885
|
-
|
|
4886
|
-
|
|
4887
|
-
return of(overallTransitionState)
|
|
4888
|
-
.pipe(
|
|
4889
|
-
// Store the Navigation object
|
|
4890
|
-
tap(t => {
|
|
4891
|
-
this.currentNavigation = {
|
|
4892
|
-
id: t.id,
|
|
4893
|
-
initialUrl: t.rawUrl,
|
|
4894
|
-
extractedUrl: t.extractedUrl,
|
|
4895
|
-
trigger: t.source,
|
|
4896
|
-
extras: t.extras,
|
|
4897
|
-
previousNavigation: this.lastSuccessfulNavigation ?
|
|
4898
|
-
{ ...this.lastSuccessfulNavigation, previousNavigation: null } :
|
|
4899
|
-
null
|
|
4900
|
-
};
|
|
4901
|
-
}), switchMap(t => {
|
|
4902
|
-
const browserUrlTree = this.browserUrlTree.toString();
|
|
4903
|
-
const urlTransition = !this.navigated ||
|
|
4904
|
-
t.extractedUrl.toString() !== browserUrlTree ||
|
|
4905
|
-
// Navigations which succeed or ones which fail and are cleaned up
|
|
4906
|
-
// correctly should result in `browserUrlTree` and `currentUrlTree`
|
|
4907
|
-
// matching. If this is not the case, assume something went wrong and
|
|
4908
|
-
// try processing the URL again.
|
|
4909
|
-
browserUrlTree !== this.currentUrlTree.toString();
|
|
4910
|
-
const processCurrentUrl = (this.onSameUrlNavigation === 'reload' ? true : urlTransition) &&
|
|
4911
|
-
this.urlHandlingStrategy.shouldProcessUrl(t.rawUrl);
|
|
4912
|
-
if (processCurrentUrl) {
|
|
4913
|
-
// If the source of the navigation is from a browser event, the URL is
|
|
4914
|
-
// already updated. We already need to sync the internal state.
|
|
4915
|
-
if (isBrowserTriggeredNavigation(t.source)) {
|
|
4916
|
-
this.browserUrlTree = t.extractedUrl;
|
|
4917
|
-
}
|
|
4918
|
-
return of(t).pipe(
|
|
4919
|
-
// Fire NavigationStart event
|
|
4920
|
-
switchMap(t => {
|
|
4921
|
-
const transition = this.transitions.getValue();
|
|
4922
|
-
eventsSubject.next(new NavigationStart(t.id, this.serializeUrl(t.extractedUrl), t.source, t.restoredState));
|
|
4923
|
-
if (transition !== this.transitions.getValue()) {
|
|
4924
|
-
return EMPTY;
|
|
4925
|
-
}
|
|
4926
|
-
// This delay is required to match old behavior that forced
|
|
4927
|
-
// navigation to always be async
|
|
4928
|
-
return Promise.resolve(t);
|
|
4929
|
-
}),
|
|
4930
|
-
// ApplyRedirects
|
|
4931
|
-
applyRedirects(this.ngModule.injector, this.configLoader, this.urlSerializer, this.config),
|
|
4932
|
-
// Update the currentNavigation
|
|
4933
|
-
// `urlAfterRedirects` is guaranteed to be set after this point
|
|
4934
|
-
tap(t => {
|
|
4935
|
-
this.currentNavigation = {
|
|
4936
|
-
...this.currentNavigation,
|
|
4937
|
-
finalUrl: t.urlAfterRedirects
|
|
4938
|
-
};
|
|
4939
|
-
overallTransitionState.urlAfterRedirects = t.urlAfterRedirects;
|
|
4940
|
-
}),
|
|
4941
|
-
// Recognize
|
|
4942
|
-
recognize(this.ngModule.injector, this.rootComponentType, this.config, this.urlSerializer, this.paramsInheritanceStrategy),
|
|
4943
|
-
// Update URL if in `eager` update mode
|
|
4944
|
-
tap(t => {
|
|
4945
|
-
overallTransitionState.targetSnapshot = t.targetSnapshot;
|
|
4946
|
-
if (this.urlUpdateStrategy === 'eager') {
|
|
4947
|
-
if (!t.extras.skipLocationChange) {
|
|
4948
|
-
const rawUrl = this.urlHandlingStrategy.merge(t.urlAfterRedirects, t.rawUrl);
|
|
4949
|
-
this.setBrowserUrl(rawUrl, t);
|
|
4950
|
-
}
|
|
4951
|
-
this.browserUrlTree = t.urlAfterRedirects;
|
|
4952
|
-
}
|
|
4953
|
-
// Fire RoutesRecognized
|
|
4954
|
-
const routesRecognized = new RoutesRecognized(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(t.urlAfterRedirects), t.targetSnapshot);
|
|
4955
|
-
eventsSubject.next(routesRecognized);
|
|
4956
|
-
}));
|
|
4957
|
-
}
|
|
4958
|
-
else {
|
|
4959
|
-
const processPreviousUrl = urlTransition && this.rawUrlTree &&
|
|
4960
|
-
this.urlHandlingStrategy.shouldProcessUrl(this.rawUrlTree);
|
|
4961
|
-
/* When the current URL shouldn't be processed, but the previous one
|
|
4962
|
-
* was, we handle this "error condition" by navigating to the
|
|
4963
|
-
* previously successful URL, but leaving the URL intact.*/
|
|
4964
|
-
if (processPreviousUrl) {
|
|
4965
|
-
const { id, extractedUrl, source, restoredState, extras } = t;
|
|
4966
|
-
const navStart = new NavigationStart(id, this.serializeUrl(extractedUrl), source, restoredState);
|
|
4967
|
-
eventsSubject.next(navStart);
|
|
4968
|
-
const targetSnapshot = createEmptyState(extractedUrl, this.rootComponentType).snapshot;
|
|
4969
|
-
overallTransitionState = {
|
|
4970
|
-
...t,
|
|
4971
|
-
targetSnapshot,
|
|
4972
|
-
urlAfterRedirects: extractedUrl,
|
|
4973
|
-
extras: { ...extras, skipLocationChange: false, replaceUrl: false },
|
|
4974
|
-
};
|
|
4975
|
-
return of(overallTransitionState);
|
|
4976
|
-
}
|
|
4977
|
-
else {
|
|
4978
|
-
/* When neither the current or previous URL can be processed, do
|
|
4979
|
-
* nothing other than update router's internal reference to the
|
|
4980
|
-
* current "settled" URL. This way the next navigation will be coming
|
|
4981
|
-
* from the current URL in the browser.
|
|
4982
|
-
*/
|
|
4983
|
-
this.rawUrlTree = t.rawUrl;
|
|
4984
|
-
t.resolve(null);
|
|
4985
|
-
return EMPTY;
|
|
4986
|
-
}
|
|
4987
|
-
}
|
|
4988
|
-
}),
|
|
4989
|
-
// --- GUARDS ---
|
|
4990
|
-
tap(t => {
|
|
4991
|
-
const guardsStart = new GuardsCheckStart(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(t.urlAfterRedirects), t.targetSnapshot);
|
|
4992
|
-
this.triggerEvent(guardsStart);
|
|
4993
|
-
}), map(t => {
|
|
4994
|
-
overallTransitionState = {
|
|
4995
|
-
...t,
|
|
4996
|
-
guards: getAllRouteGuards(t.targetSnapshot, t.currentSnapshot, this.rootContexts)
|
|
4997
|
-
};
|
|
4998
|
-
return overallTransitionState;
|
|
4999
|
-
}), checkGuards(this.ngModule.injector, (evt) => this.triggerEvent(evt)), tap(t => {
|
|
5000
|
-
overallTransitionState.guardsResult = t.guardsResult;
|
|
5001
|
-
if (isUrlTree(t.guardsResult)) {
|
|
5002
|
-
throw redirectingNavigationError(this.urlSerializer, t.guardsResult);
|
|
5003
|
-
}
|
|
5004
|
-
const guardsEnd = new GuardsCheckEnd(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(t.urlAfterRedirects), t.targetSnapshot, !!t.guardsResult);
|
|
5005
|
-
this.triggerEvent(guardsEnd);
|
|
5006
|
-
}), filter(t => {
|
|
5007
|
-
if (!t.guardsResult) {
|
|
5008
|
-
this.restoreHistory(t);
|
|
5009
|
-
this.cancelNavigationTransition(t, '', 3 /* NavigationCancellationCode.GuardRejected */);
|
|
5010
|
-
return false;
|
|
5011
|
-
}
|
|
5012
|
-
return true;
|
|
5013
|
-
}),
|
|
5014
|
-
// --- RESOLVE ---
|
|
5015
|
-
switchTap(t => {
|
|
5016
|
-
if (t.guards.canActivateChecks.length) {
|
|
5017
|
-
return of(t).pipe(tap(t => {
|
|
5018
|
-
const resolveStart = new ResolveStart(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(t.urlAfterRedirects), t.targetSnapshot);
|
|
5019
|
-
this.triggerEvent(resolveStart);
|
|
5020
|
-
}), switchMap(t => {
|
|
5021
|
-
let dataResolved = false;
|
|
5022
|
-
return of(t).pipe(resolveData(this.paramsInheritanceStrategy, this.ngModule.injector), tap({
|
|
5023
|
-
next: () => dataResolved = true,
|
|
5024
|
-
complete: () => {
|
|
5025
|
-
if (!dataResolved) {
|
|
5026
|
-
this.restoreHistory(t);
|
|
5027
|
-
this.cancelNavigationTransition(t, NG_DEV_MODE$2 ?
|
|
5028
|
-
`At least one route resolver didn't emit any value.` :
|
|
5029
|
-
'', 2 /* NavigationCancellationCode.NoDataFromResolver */);
|
|
5030
|
-
}
|
|
5031
|
-
}
|
|
5032
|
-
}));
|
|
5033
|
-
}), tap(t => {
|
|
5034
|
-
const resolveEnd = new ResolveEnd(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(t.urlAfterRedirects), t.targetSnapshot);
|
|
5035
|
-
this.triggerEvent(resolveEnd);
|
|
5036
|
-
}));
|
|
5037
|
-
}
|
|
5038
|
-
return undefined;
|
|
5039
|
-
}),
|
|
5040
|
-
// --- LOAD COMPONENTS ---
|
|
5041
|
-
switchTap((t) => {
|
|
5042
|
-
const loadComponents = (route) => {
|
|
5043
|
-
const loaders = [];
|
|
5044
|
-
if (route.routeConfig?.loadComponent &&
|
|
5045
|
-
!route.routeConfig._loadedComponent) {
|
|
5046
|
-
loaders.push(this.configLoader.loadComponent(route.routeConfig)
|
|
5047
|
-
.pipe(tap(loadedComponent => {
|
|
5048
|
-
route.component = loadedComponent;
|
|
5049
|
-
}), map(() => void 0)));
|
|
5050
|
-
}
|
|
5051
|
-
for (const child of route.children) {
|
|
5052
|
-
loaders.push(...loadComponents(child));
|
|
5053
|
-
}
|
|
5054
|
-
return loaders;
|
|
5055
|
-
};
|
|
5056
|
-
return combineLatest(loadComponents(t.targetSnapshot.root))
|
|
5057
|
-
.pipe(defaultIfEmpty(), take(1));
|
|
5058
|
-
}), switchTap(() => this.afterPreactivation()), map((t) => {
|
|
5059
|
-
const targetRouterState = createRouterState(this.routeReuseStrategy, t.targetSnapshot, t.currentRouterState);
|
|
5060
|
-
overallTransitionState = { ...t, targetRouterState };
|
|
5061
|
-
return (overallTransitionState);
|
|
5062
|
-
}),
|
|
5063
|
-
/* Once here, we are about to activate synchronously. The assumption is
|
|
5064
|
-
this will succeed, and user code may read from the Router service.
|
|
5065
|
-
Therefore before activation, we need to update router properties storing
|
|
5066
|
-
the current URL and the RouterState, as well as updated the browser URL.
|
|
5067
|
-
All this should happen *before* activating. */
|
|
5068
|
-
tap((t) => {
|
|
5069
|
-
this.currentUrlTree = t.urlAfterRedirects;
|
|
5070
|
-
this.rawUrlTree =
|
|
5071
|
-
this.urlHandlingStrategy.merge(t.urlAfterRedirects, t.rawUrl);
|
|
5072
|
-
this.routerState = t.targetRouterState;
|
|
5073
|
-
if (this.urlUpdateStrategy === 'deferred') {
|
|
5074
|
-
if (!t.extras.skipLocationChange) {
|
|
5075
|
-
this.setBrowserUrl(this.rawUrlTree, t);
|
|
5076
|
-
}
|
|
5077
|
-
this.browserUrlTree = t.urlAfterRedirects;
|
|
5078
|
-
}
|
|
5079
|
-
}), activateRoutes(this.rootContexts, this.routeReuseStrategy, (evt) => this.triggerEvent(evt)), tap({
|
|
5080
|
-
next() {
|
|
5081
|
-
completed = true;
|
|
5082
|
-
},
|
|
5083
|
-
complete() {
|
|
5084
|
-
completed = true;
|
|
5085
|
-
}
|
|
5086
|
-
}), finalize(() => {
|
|
5087
|
-
/* When the navigation stream finishes either through error or success,
|
|
5088
|
-
* we set the `completed` or `errored` flag. However, there are some
|
|
5089
|
-
* situations where we could get here without either of those being set.
|
|
5090
|
-
* For instance, a redirect during NavigationStart. Therefore, this is a
|
|
5091
|
-
* catch-all to make sure the NavigationCancel event is fired when a
|
|
5092
|
-
* navigation gets cancelled but not caught by other means. */
|
|
5093
|
-
if (!completed && !errored) {
|
|
5094
|
-
const cancelationReason = NG_DEV_MODE$2 ?
|
|
5095
|
-
`Navigation ID ${overallTransitionState
|
|
5096
|
-
.id} is not equal to the current navigation id ${this.navigationId}` :
|
|
5097
|
-
'';
|
|
5098
|
-
this.cancelNavigationTransition(overallTransitionState, cancelationReason, 1 /* NavigationCancellationCode.SupersededByNewNavigation */);
|
|
5099
|
-
}
|
|
5100
|
-
// Only clear current navigation if it is still set to the one that
|
|
5101
|
-
// finalized.
|
|
5102
|
-
if (this.currentNavigation?.id === overallTransitionState.id) {
|
|
5103
|
-
this.currentNavigation = null;
|
|
5104
|
-
}
|
|
5105
|
-
}), catchError((e) => {
|
|
5106
|
-
errored = true;
|
|
5107
|
-
/* This error type is issued during Redirect, and is handled as a
|
|
5108
|
-
* cancellation rather than an error. */
|
|
5109
|
-
if (isNavigationCancelingError$1(e)) {
|
|
5110
|
-
if (!isRedirectingNavigationCancelingError$1(e)) {
|
|
5111
|
-
// Set property only if we're not redirecting. If we landed on a page
|
|
5112
|
-
// and redirect to `/` route, the new navigation is going to see the
|
|
5113
|
-
// `/` isn't a change from the default currentUrlTree and won't
|
|
5114
|
-
// navigate. This is only applicable with initial navigation, so
|
|
5115
|
-
// setting `navigated` only when not redirecting resolves this
|
|
5116
|
-
// scenario.
|
|
5117
|
-
this.navigated = true;
|
|
5118
|
-
this.restoreHistory(overallTransitionState, true);
|
|
5119
|
-
}
|
|
5120
|
-
const navCancel = new NavigationCancel(overallTransitionState.id, this.serializeUrl(overallTransitionState.extractedUrl), e.message, e.cancellationCode);
|
|
5121
|
-
eventsSubject.next(navCancel);
|
|
5122
|
-
// When redirecting, we need to delay resolving the navigation
|
|
5123
|
-
// promise and push it to the redirect navigation
|
|
5124
|
-
if (!isRedirectingNavigationCancelingError$1(e)) {
|
|
5125
|
-
overallTransitionState.resolve(false);
|
|
5126
|
-
}
|
|
5127
|
-
else {
|
|
5128
|
-
const mergedTree = this.urlHandlingStrategy.merge(e.url, this.rawUrlTree);
|
|
5129
|
-
const extras = {
|
|
5130
|
-
skipLocationChange: overallTransitionState.extras.skipLocationChange,
|
|
5131
|
-
// The URL is already updated at this point if we have 'eager' URL
|
|
5132
|
-
// updates or if the navigation was triggered by the browser (back
|
|
5133
|
-
// button, URL bar, etc). We want to replace that item in history
|
|
5134
|
-
// if the navigation is rejected.
|
|
5135
|
-
replaceUrl: this.urlUpdateStrategy === 'eager' ||
|
|
5136
|
-
isBrowserTriggeredNavigation(overallTransitionState.source)
|
|
5137
|
-
};
|
|
5138
|
-
this.scheduleNavigation(mergedTree, 'imperative', null, extras, {
|
|
5139
|
-
resolve: overallTransitionState.resolve,
|
|
5140
|
-
reject: overallTransitionState.reject,
|
|
5141
|
-
promise: overallTransitionState.promise
|
|
5142
|
-
});
|
|
5143
|
-
}
|
|
5144
|
-
/* All other errors should reset to the router's internal URL reference
|
|
5145
|
-
* to the pre-error state. */
|
|
5146
|
-
}
|
|
5147
|
-
else {
|
|
5148
|
-
this.restoreHistory(overallTransitionState, true);
|
|
5149
|
-
const navError = new NavigationError(overallTransitionState.id, this.serializeUrl(overallTransitionState.extractedUrl), e, overallTransitionState.targetSnapshot ?? undefined);
|
|
5150
|
-
eventsSubject.next(navError);
|
|
5151
|
-
try {
|
|
5152
|
-
overallTransitionState.resolve(this.errorHandler(e));
|
|
5153
|
-
}
|
|
5154
|
-
catch (ee) {
|
|
5155
|
-
overallTransitionState.reject(ee);
|
|
5156
|
-
}
|
|
5157
|
-
}
|
|
5158
|
-
return EMPTY;
|
|
5159
|
-
}));
|
|
5160
|
-
// TODO(jasonaden): remove cast once g3 is on updated TypeScript
|
|
5161
|
-
}));
|
|
5237
|
+
/**
|
|
5238
|
+
* An event stream for routing events.
|
|
5239
|
+
*/
|
|
5240
|
+
get events() {
|
|
5241
|
+
// TODO(atscott): This _should_ be events.asObservable(). However, this change requires internal
|
|
5242
|
+
// cleanup: tests are doing `(route.events as Subject<Event>).next(...)`. This isn't
|
|
5243
|
+
// allowed/supported but we still have to fix these or file bugs against the teams before making
|
|
5244
|
+
// the change.
|
|
5245
|
+
return this.navigationTransitions.events;
|
|
5162
5246
|
}
|
|
5163
5247
|
/**
|
|
5164
5248
|
* @internal
|
|
@@ -5170,15 +5254,12 @@ class Router {
|
|
|
5170
5254
|
// this will simplify the lifecycle of the router.
|
|
5171
5255
|
this.routerState.root.component = this.rootComponentType;
|
|
5172
5256
|
}
|
|
5173
|
-
setTransition(t) {
|
|
5174
|
-
this.transitions.next({ ...this.transitions.value, ...t });
|
|
5175
|
-
}
|
|
5176
5257
|
/**
|
|
5177
5258
|
* Sets up the location change listener and performs the initial navigation.
|
|
5178
5259
|
*/
|
|
5179
5260
|
initialNavigation() {
|
|
5180
5261
|
this.setUpLocationChangeListener();
|
|
5181
|
-
if (this.
|
|
5262
|
+
if (!this.navigationTransitions.hasRequestedNavigation) {
|
|
5182
5263
|
this.navigateByUrl(this.location.path(true), { replaceUrl: true });
|
|
5183
5264
|
}
|
|
5184
5265
|
}
|
|
@@ -5199,11 +5280,18 @@ class Router {
|
|
|
5199
5280
|
// hybrid apps.
|
|
5200
5281
|
setTimeout(() => {
|
|
5201
5282
|
const extras = { replaceUrl: true };
|
|
5202
|
-
//
|
|
5203
|
-
//
|
|
5204
|
-
|
|
5205
|
-
|
|
5206
|
-
|
|
5283
|
+
// TODO: restoredState should always include the entire state, regardless
|
|
5284
|
+
// of navigationId. This requires a breaking change to update the type on
|
|
5285
|
+
// NavigationStart’s restoredState, which currently requires navigationId
|
|
5286
|
+
// to always be present. The Router used to only restore history state if
|
|
5287
|
+
// a navigationId was present.
|
|
5288
|
+
// The stored navigationId is used by the RouterScroller to retrieve the scroll
|
|
5289
|
+
// position for the page.
|
|
5290
|
+
const restoredState = event.state?.navigationId ? event.state : null;
|
|
5291
|
+
// Separate to NavigationStart.restoredState, we must also restore the state to
|
|
5292
|
+
// history.state and generate a new navigationId, since it will be overwritten
|
|
5293
|
+
if (event.state) {
|
|
5294
|
+
const stateCopy = { ...event.state };
|
|
5207
5295
|
delete stateCopy.navigationId;
|
|
5208
5296
|
delete stateCopy.ɵrouterPageId;
|
|
5209
5297
|
if (Object.keys(stateCopy).length !== 0) {
|
|
@@ -5211,7 +5299,7 @@ class Router {
|
|
|
5211
5299
|
}
|
|
5212
5300
|
}
|
|
5213
5301
|
const urlTree = this.parseUrl(event['url']);
|
|
5214
|
-
this.scheduleNavigation(urlTree, source,
|
|
5302
|
+
this.scheduleNavigation(urlTree, source, restoredState, extras);
|
|
5215
5303
|
}, 0);
|
|
5216
5304
|
}
|
|
5217
5305
|
});
|
|
@@ -5226,11 +5314,7 @@ class Router {
|
|
|
5226
5314
|
* and `null` when idle.
|
|
5227
5315
|
*/
|
|
5228
5316
|
getCurrentNavigation() {
|
|
5229
|
-
return this.currentNavigation;
|
|
5230
|
-
}
|
|
5231
|
-
/** @internal */
|
|
5232
|
-
triggerEvent(event) {
|
|
5233
|
-
this.events.next(event);
|
|
5317
|
+
return this.navigationTransitions.currentNavigation;
|
|
5234
5318
|
}
|
|
5235
5319
|
/**
|
|
5236
5320
|
* Resets the route configuration used for navigation and generating links.
|
|
@@ -5260,7 +5344,7 @@ class Router {
|
|
|
5260
5344
|
}
|
|
5261
5345
|
/** Disposes of the router. */
|
|
5262
5346
|
dispose() {
|
|
5263
|
-
this.
|
|
5347
|
+
this.navigationTransitions.complete();
|
|
5264
5348
|
if (this.locationSubscription) {
|
|
5265
5349
|
this.locationSubscription.unsubscribe();
|
|
5266
5350
|
this.locationSubscription = undefined;
|
|
@@ -5445,20 +5529,7 @@ class Router {
|
|
|
5445
5529
|
return result;
|
|
5446
5530
|
}, {});
|
|
5447
5531
|
}
|
|
5448
|
-
|
|
5449
|
-
this.navigations.subscribe(t => {
|
|
5450
|
-
this.navigated = true;
|
|
5451
|
-
this.lastSuccessfulId = t.id;
|
|
5452
|
-
this.currentPageId = t.targetPageId;
|
|
5453
|
-
this.events
|
|
5454
|
-
.next(new NavigationEnd(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(this.currentUrlTree)));
|
|
5455
|
-
this.lastSuccessfulNavigation = this.currentNavigation;
|
|
5456
|
-
this.titleStrategy?.updateTitle(this.routerState.snapshot);
|
|
5457
|
-
t.resolve(true);
|
|
5458
|
-
}, e => {
|
|
5459
|
-
this.console.warn(`Unhandled Navigation Error: ${e}`);
|
|
5460
|
-
});
|
|
5461
|
-
}
|
|
5532
|
+
/** @internal */
|
|
5462
5533
|
scheduleNavigation(rawUrl, source, restoredState, extras, priorPromise) {
|
|
5463
5534
|
if (this.disposed) {
|
|
5464
5535
|
return Promise.resolve(false);
|
|
@@ -5477,7 +5548,6 @@ class Router {
|
|
|
5477
5548
|
reject = rej;
|
|
5478
5549
|
});
|
|
5479
5550
|
}
|
|
5480
|
-
const id = ++this.navigationId;
|
|
5481
5551
|
let targetPageId;
|
|
5482
5552
|
if (this.canceledNavigationResolution === 'computed') {
|
|
5483
5553
|
const isInitialPage = this.currentPageId === 0;
|
|
@@ -5505,13 +5575,12 @@ class Router {
|
|
|
5505
5575
|
// This is unused when `canceledNavigationResolution` is not computed.
|
|
5506
5576
|
targetPageId = 0;
|
|
5507
5577
|
}
|
|
5508
|
-
this.
|
|
5509
|
-
id,
|
|
5578
|
+
this.navigationTransitions.handleNavigationRequest({
|
|
5510
5579
|
targetPageId,
|
|
5511
5580
|
source,
|
|
5512
5581
|
restoredState,
|
|
5513
5582
|
currentUrlTree: this.currentUrlTree,
|
|
5514
|
-
currentRawUrl: this.
|
|
5583
|
+
currentRawUrl: this.currentUrlTree,
|
|
5515
5584
|
rawUrl,
|
|
5516
5585
|
extras,
|
|
5517
5586
|
resolve,
|
|
@@ -5526,10 +5595,14 @@ class Router {
|
|
|
5526
5595
|
return Promise.reject(e);
|
|
5527
5596
|
});
|
|
5528
5597
|
}
|
|
5529
|
-
|
|
5598
|
+
/** @internal */
|
|
5599
|
+
setBrowserUrl(url, transition) {
|
|
5530
5600
|
const path = this.urlSerializer.serialize(url);
|
|
5531
|
-
const state = {
|
|
5532
|
-
|
|
5601
|
+
const state = {
|
|
5602
|
+
...transition.extras.state,
|
|
5603
|
+
...this.generateNgRouterState(transition.id, transition.targetPageId)
|
|
5604
|
+
};
|
|
5605
|
+
if (this.location.isCurrentPathEqualTo(path) || !!transition.extras.replaceUrl) {
|
|
5533
5606
|
this.location.replaceState(path, '', state);
|
|
5534
5607
|
}
|
|
5535
5608
|
else {
|
|
@@ -5539,28 +5612,30 @@ class Router {
|
|
|
5539
5612
|
/**
|
|
5540
5613
|
* Performs the necessary rollback action to restore the browser URL to the
|
|
5541
5614
|
* state before the transition.
|
|
5615
|
+
* @internal
|
|
5542
5616
|
*/
|
|
5543
|
-
restoreHistory(
|
|
5617
|
+
restoreHistory(transition, restoringFromCaughtError = false) {
|
|
5544
5618
|
if (this.canceledNavigationResolution === 'computed') {
|
|
5545
|
-
const targetPagePosition = this.currentPageId -
|
|
5619
|
+
const targetPagePosition = this.currentPageId - transition.targetPageId;
|
|
5546
5620
|
// The navigator change the location before triggered the browser event,
|
|
5547
5621
|
// so we need to go back to the current url if the navigation is canceled.
|
|
5548
5622
|
// Also, when navigation gets cancelled while using url update strategy eager, then we need to
|
|
5549
5623
|
// go back. Because, when `urlUpdateStrategy` is `eager`; `setBrowserUrl` method is called
|
|
5550
5624
|
// before any verification.
|
|
5551
|
-
const browserUrlUpdateOccurred = (
|
|
5552
|
-
this.currentUrlTree === this.
|
|
5625
|
+
const browserUrlUpdateOccurred = (transition.source === 'popstate' || this.urlUpdateStrategy === 'eager' ||
|
|
5626
|
+
this.currentUrlTree === this.getCurrentNavigation()?.finalUrl);
|
|
5553
5627
|
if (browserUrlUpdateOccurred && targetPagePosition !== 0) {
|
|
5554
5628
|
this.location.historyGo(targetPagePosition);
|
|
5555
5629
|
}
|
|
5556
|
-
else if (this.currentUrlTree === this.
|
|
5630
|
+
else if (this.currentUrlTree === this.getCurrentNavigation()?.finalUrl &&
|
|
5631
|
+
targetPagePosition === 0) {
|
|
5557
5632
|
// We got to the activation stage (where currentUrlTree is set to the navigation's
|
|
5558
5633
|
// finalUrl), but we weren't moving anywhere in history (skipLocationChange or replaceUrl).
|
|
5559
5634
|
// We still need to reset the router state back to what it was when the navigation started.
|
|
5560
|
-
this.resetState(
|
|
5635
|
+
this.resetState(transition);
|
|
5561
5636
|
// TODO(atscott): resetting the `browserUrlTree` should really be done in `resetState`.
|
|
5562
5637
|
// Investigate if this can be done by running TGP.
|
|
5563
|
-
this.browserUrlTree =
|
|
5638
|
+
this.browserUrlTree = transition.currentUrlTree;
|
|
5564
5639
|
this.resetUrlToCurrentUrlTree();
|
|
5565
5640
|
}
|
|
5566
5641
|
else {
|
|
@@ -5574,7 +5649,7 @@ class Router {
|
|
|
5574
5649
|
// reject. For 'eager' navigations, it seems like we also really should reset the state
|
|
5575
5650
|
// because the navigation was cancelled. Investigate if this can be done by running TGP.
|
|
5576
5651
|
if (restoringFromCaughtError) {
|
|
5577
|
-
this.resetState(
|
|
5652
|
+
this.resetState(transition);
|
|
5578
5653
|
}
|
|
5579
5654
|
this.resetUrlToCurrentUrlTree();
|
|
5580
5655
|
}
|
|
@@ -5592,11 +5667,6 @@ class Router {
|
|
|
5592
5667
|
resetUrlToCurrentUrlTree() {
|
|
5593
5668
|
this.location.replaceState(this.urlSerializer.serialize(this.rawUrlTree), '', this.generateNgRouterState(this.lastSuccessfulId, this.currentPageId));
|
|
5594
5669
|
}
|
|
5595
|
-
cancelNavigationTransition(t, reason, code) {
|
|
5596
|
-
const navCancel = new NavigationCancel(t.id, this.serializeUrl(t.extractedUrl), reason, code);
|
|
5597
|
-
this.triggerEvent(navCancel);
|
|
5598
|
-
t.resolve(false);
|
|
5599
|
-
}
|
|
5600
5670
|
generateNgRouterState(navigationId, routerPageId) {
|
|
5601
5671
|
if (this.canceledNavigationResolution === 'computed') {
|
|
5602
5672
|
return { navigationId, ɵrouterPageId: routerPageId };
|
|
@@ -5604,9 +5674,9 @@ class Router {
|
|
|
5604
5674
|
return { navigationId };
|
|
5605
5675
|
}
|
|
5606
5676
|
}
|
|
5607
|
-
Router.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.
|
|
5608
|
-
Router.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.
|
|
5609
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.
|
|
5677
|
+
Router.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: Router, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
|
|
5678
|
+
Router.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: Router, providedIn: 'root', useFactory: setupRouter });
|
|
5679
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: Router, decorators: [{
|
|
5610
5680
|
type: Injectable,
|
|
5611
5681
|
args: [{
|
|
5612
5682
|
providedIn: 'root',
|
|
@@ -5621,9 +5691,6 @@ function validateCommands(commands) {
|
|
|
5621
5691
|
}
|
|
5622
5692
|
}
|
|
5623
5693
|
}
|
|
5624
|
-
function isBrowserTriggeredNavigation(source) {
|
|
5625
|
-
return source !== 'imperative';
|
|
5626
|
-
}
|
|
5627
5694
|
|
|
5628
5695
|
/**
|
|
5629
5696
|
* @license
|
|
@@ -5905,9 +5972,9 @@ class RouterLink {
|
|
|
5905
5972
|
});
|
|
5906
5973
|
}
|
|
5907
5974
|
}
|
|
5908
|
-
RouterLink.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.
|
|
5909
|
-
RouterLink.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.0.
|
|
5910
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.
|
|
5975
|
+
RouterLink.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", 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 });
|
|
5976
|
+
RouterLink.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.0.2", type: RouterLink, isStandalone: true, selector: "[routerLink]", inputs: { target: "target", queryParams: "queryParams", fragment: "fragment", queryParamsHandling: "queryParamsHandling", state: "state", relativeTo: "relativeTo", preserveFragment: "preserveFragment", skipLocationChange: "skipLocationChange", replaceUrl: "replaceUrl", 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 });
|
|
5977
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: RouterLink, decorators: [{
|
|
5911
5978
|
type: Directive,
|
|
5912
5979
|
args: [{
|
|
5913
5980
|
selector: '[routerLink]',
|
|
@@ -6132,9 +6199,9 @@ class RouterLinkActive {
|
|
|
6132
6199
|
return this.link && isActiveCheckFn(this.link) || this.links.some(isActiveCheckFn);
|
|
6133
6200
|
}
|
|
6134
6201
|
}
|
|
6135
|
-
RouterLinkActive.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.
|
|
6136
|
-
RouterLinkActive.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.0.
|
|
6137
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.
|
|
6202
|
+
RouterLinkActive.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: RouterLinkActive, deps: [{ token: Router }, { token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }, { token: RouterLink, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
|
|
6203
|
+
RouterLinkActive.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.0.2", 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 });
|
|
6204
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: RouterLinkActive, decorators: [{
|
|
6138
6205
|
type: Directive,
|
|
6139
6206
|
args: [{
|
|
6140
6207
|
selector: '[routerLinkActive]',
|
|
@@ -6194,9 +6261,9 @@ class PreloadAllModules {
|
|
|
6194
6261
|
return fn().pipe(catchError(() => of(null)));
|
|
6195
6262
|
}
|
|
6196
6263
|
}
|
|
6197
|
-
PreloadAllModules.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.
|
|
6198
|
-
PreloadAllModules.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.
|
|
6199
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.
|
|
6264
|
+
PreloadAllModules.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: PreloadAllModules, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
6265
|
+
PreloadAllModules.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: PreloadAllModules, providedIn: 'root' });
|
|
6266
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: PreloadAllModules, decorators: [{
|
|
6200
6267
|
type: Injectable,
|
|
6201
6268
|
args: [{ providedIn: 'root' }]
|
|
6202
6269
|
}] });
|
|
@@ -6214,9 +6281,9 @@ class NoPreloading {
|
|
|
6214
6281
|
return of(null);
|
|
6215
6282
|
}
|
|
6216
6283
|
}
|
|
6217
|
-
NoPreloading.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.
|
|
6218
|
-
NoPreloading.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.
|
|
6219
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.
|
|
6284
|
+
NoPreloading.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: NoPreloading, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
6285
|
+
NoPreloading.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: NoPreloading, providedIn: 'root' });
|
|
6286
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: NoPreloading, decorators: [{
|
|
6220
6287
|
type: Injectable,
|
|
6221
6288
|
args: [{ providedIn: 'root' }]
|
|
6222
6289
|
}] });
|
|
@@ -6310,9 +6377,9 @@ class RouterPreloader {
|
|
|
6310
6377
|
});
|
|
6311
6378
|
}
|
|
6312
6379
|
}
|
|
6313
|
-
RouterPreloader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.
|
|
6314
|
-
RouterPreloader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.
|
|
6315
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.
|
|
6380
|
+
RouterPreloader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: RouterPreloader, deps: [{ token: Router }, { token: i0.Compiler }, { token: i0.EnvironmentInjector }, { token: PreloadingStrategy }, { token: RouterConfigLoader }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
6381
|
+
RouterPreloader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: RouterPreloader, providedIn: 'root' });
|
|
6382
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: RouterPreloader, decorators: [{
|
|
6316
6383
|
type: Injectable,
|
|
6317
6384
|
args: [{ providedIn: 'root' }]
|
|
6318
6385
|
}], ctorParameters: function () { return [{ type: Router }, { type: i0.Compiler }, { type: i0.EnvironmentInjector }, { type: PreloadingStrategy }, { type: RouterConfigLoader }]; } });
|
|
@@ -6326,9 +6393,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImpor
|
|
|
6326
6393
|
*/
|
|
6327
6394
|
const ROUTER_SCROLLER = new InjectionToken('');
|
|
6328
6395
|
class RouterScroller {
|
|
6329
|
-
|
|
6330
|
-
|
|
6331
|
-
this.
|
|
6396
|
+
/** @nodoc */
|
|
6397
|
+
constructor(urlSerializer, transitions, viewportScroller, zone, options = {}) {
|
|
6398
|
+
this.urlSerializer = urlSerializer;
|
|
6399
|
+
this.transitions = transitions;
|
|
6332
6400
|
this.viewportScroller = viewportScroller;
|
|
6333
6401
|
this.zone = zone;
|
|
6334
6402
|
this.options = options;
|
|
@@ -6351,7 +6419,7 @@ class RouterScroller {
|
|
|
6351
6419
|
this.scrollEventsSubscription = this.consumeScrollEvents();
|
|
6352
6420
|
}
|
|
6353
6421
|
createScrollEvents() {
|
|
6354
|
-
return this.
|
|
6422
|
+
return this.transitions.events.subscribe(e => {
|
|
6355
6423
|
if (e instanceof NavigationStart) {
|
|
6356
6424
|
// store the scroll position of the current stable navigations.
|
|
6357
6425
|
this.store[this.lastId] = this.viewportScroller.getScrollPosition();
|
|
@@ -6360,12 +6428,12 @@ class RouterScroller {
|
|
|
6360
6428
|
}
|
|
6361
6429
|
else if (e instanceof NavigationEnd) {
|
|
6362
6430
|
this.lastId = e.id;
|
|
6363
|
-
this.scheduleScrollEvent(e, this.
|
|
6431
|
+
this.scheduleScrollEvent(e, this.urlSerializer.parse(e.urlAfterRedirects).fragment);
|
|
6364
6432
|
}
|
|
6365
6433
|
});
|
|
6366
6434
|
}
|
|
6367
6435
|
consumeScrollEvents() {
|
|
6368
|
-
return this.
|
|
6436
|
+
return this.transitions.events.subscribe(e => {
|
|
6369
6437
|
if (!(e instanceof Scroll))
|
|
6370
6438
|
return;
|
|
6371
6439
|
// a popstate event. The pop state event will always ignore anchor scrolling.
|
|
@@ -6395,26 +6463,22 @@ class RouterScroller {
|
|
|
6395
6463
|
// component by executing its update block of the template function.
|
|
6396
6464
|
setTimeout(() => {
|
|
6397
6465
|
this.zone.run(() => {
|
|
6398
|
-
this.
|
|
6466
|
+
this.transitions.events.next(new Scroll(routerEvent, this.lastSource === 'popstate' ? this.store[this.restoredId] : null, anchor));
|
|
6399
6467
|
});
|
|
6400
6468
|
}, 0);
|
|
6401
6469
|
});
|
|
6402
6470
|
}
|
|
6403
6471
|
/** @nodoc */
|
|
6404
6472
|
ngOnDestroy() {
|
|
6405
|
-
|
|
6406
|
-
|
|
6407
|
-
}
|
|
6408
|
-
if (this.scrollEventsSubscription) {
|
|
6409
|
-
this.scrollEventsSubscription.unsubscribe();
|
|
6410
|
-
}
|
|
6473
|
+
this.routerEventsSubscription?.unsubscribe();
|
|
6474
|
+
this.scrollEventsSubscription?.unsubscribe();
|
|
6411
6475
|
}
|
|
6412
6476
|
}
|
|
6413
|
-
RouterScroller.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.
|
|
6414
|
-
RouterScroller.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.
|
|
6415
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.
|
|
6477
|
+
RouterScroller.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: RouterScroller, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
|
|
6478
|
+
RouterScroller.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: RouterScroller });
|
|
6479
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: RouterScroller, decorators: [{
|
|
6416
6480
|
type: Injectable
|
|
6417
|
-
}], ctorParameters: function () { return [{ type:
|
|
6481
|
+
}], ctorParameters: function () { return [{ type: UrlSerializer }, { type: NavigationTransitions }, { type: i3.ViewportScroller }, { type: i0.NgZone }, { type: undefined }]; } });
|
|
6418
6482
|
|
|
6419
6483
|
/**
|
|
6420
6484
|
* @license
|
|
@@ -6551,10 +6615,11 @@ function withInMemoryScrolling(options = {}) {
|
|
|
6551
6615
|
const providers = [{
|
|
6552
6616
|
provide: ROUTER_SCROLLER,
|
|
6553
6617
|
useFactory: () => {
|
|
6554
|
-
const router = inject(Router);
|
|
6555
6618
|
const viewportScroller = inject(ViewportScroller);
|
|
6556
6619
|
const zone = inject(NgZone);
|
|
6557
|
-
|
|
6620
|
+
const transitions = inject(NavigationTransitions);
|
|
6621
|
+
const urlSerializer = inject(UrlSerializer);
|
|
6622
|
+
return new RouterScroller(urlSerializer, transitions, viewportScroller, zone, options);
|
|
6558
6623
|
},
|
|
6559
6624
|
}];
|
|
6560
6625
|
return routerFeature(4 /* RouterFeatureKind.InMemoryScrollingFeature */, providers);
|
|
@@ -6574,8 +6639,10 @@ function getBootstrapListener() {
|
|
|
6574
6639
|
injector.get(ROUTER_PRELOADER, null, InjectFlags.Optional)?.setUpPreloading();
|
|
6575
6640
|
injector.get(ROUTER_SCROLLER, null, InjectFlags.Optional)?.init();
|
|
6576
6641
|
router.resetRootComponentType(ref.componentTypes[0]);
|
|
6577
|
-
bootstrapDone.
|
|
6578
|
-
|
|
6642
|
+
if (!bootstrapDone.closed) {
|
|
6643
|
+
bootstrapDone.next();
|
|
6644
|
+
bootstrapDone.unsubscribe();
|
|
6645
|
+
}
|
|
6579
6646
|
};
|
|
6580
6647
|
}
|
|
6581
6648
|
/**
|
|
@@ -6623,7 +6690,6 @@ function withEnabledBlockingInitialNavigation() {
|
|
|
6623
6690
|
deps: [Injector],
|
|
6624
6691
|
useFactory: (injector) => {
|
|
6625
6692
|
const locationInitialized = injector.get(LOCATION_INITIALIZED, Promise.resolve());
|
|
6626
|
-
let initNavigation = false;
|
|
6627
6693
|
/**
|
|
6628
6694
|
* Performs the given action once the router finishes its next/current navigation.
|
|
6629
6695
|
*
|
|
@@ -6658,21 +6724,13 @@ function withEnabledBlockingInitialNavigation() {
|
|
|
6658
6724
|
// Unblock APP_INITIALIZER in case the initial navigation was canceled or errored
|
|
6659
6725
|
// without a redirect.
|
|
6660
6726
|
resolve(true);
|
|
6661
|
-
initNavigation = true;
|
|
6662
6727
|
});
|
|
6663
6728
|
router.afterPreactivation = () => {
|
|
6664
6729
|
// Unblock APP_INITIALIZER once we get to `afterPreactivation`. At this point, we
|
|
6665
6730
|
// assume activation will complete successfully (even though this is not
|
|
6666
6731
|
// guaranteed).
|
|
6667
6732
|
resolve(true);
|
|
6668
|
-
|
|
6669
|
-
if (!initNavigation) {
|
|
6670
|
-
return bootstrapDone.closed ? of(void 0) : bootstrapDone;
|
|
6671
|
-
// subsequent navigations should not be delayed
|
|
6672
|
-
}
|
|
6673
|
-
else {
|
|
6674
|
-
return of(void 0);
|
|
6675
|
-
}
|
|
6733
|
+
return bootstrapDone.closed ? of(void 0) : bootstrapDone;
|
|
6676
6734
|
};
|
|
6677
6735
|
router.initialNavigation();
|
|
6678
6736
|
});
|
|
@@ -6961,10 +7019,10 @@ class RouterModule {
|
|
|
6961
7019
|
};
|
|
6962
7020
|
}
|
|
6963
7021
|
}
|
|
6964
|
-
RouterModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.
|
|
6965
|
-
RouterModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.0.
|
|
6966
|
-
RouterModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.0.
|
|
6967
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.
|
|
7022
|
+
RouterModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: RouterModule, deps: [{ token: ROUTER_FORROOT_GUARD, optional: true }], target: i0.ɵɵFactoryTarget.NgModule });
|
|
7023
|
+
RouterModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.0.2", ngImport: i0, type: RouterModule, imports: [RouterOutlet, RouterLink, RouterLinkActive, ɵEmptyOutletComponent], exports: [RouterOutlet, RouterLink, RouterLinkActive, ɵEmptyOutletComponent] });
|
|
7024
|
+
RouterModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: RouterModule, imports: [ɵEmptyOutletComponent] });
|
|
7025
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: RouterModule, decorators: [{
|
|
6968
7026
|
type: NgModule,
|
|
6969
7027
|
args: [{
|
|
6970
7028
|
imports: ROUTER_DIRECTIVES,
|
|
@@ -6984,14 +7042,15 @@ function provideRouterScroller() {
|
|
|
6984
7042
|
return {
|
|
6985
7043
|
provide: ROUTER_SCROLLER,
|
|
6986
7044
|
useFactory: () => {
|
|
6987
|
-
const router = inject(Router);
|
|
6988
7045
|
const viewportScroller = inject(ViewportScroller);
|
|
6989
7046
|
const zone = inject(NgZone);
|
|
6990
7047
|
const config = inject(ROUTER_CONFIGURATION);
|
|
7048
|
+
const transitions = inject(NavigationTransitions);
|
|
7049
|
+
const urlSerializer = inject(UrlSerializer);
|
|
6991
7050
|
if (config.scrollOffset) {
|
|
6992
7051
|
viewportScroller.setOffset(config.scrollOffset);
|
|
6993
7052
|
}
|
|
6994
|
-
return new RouterScroller(
|
|
7053
|
+
return new RouterScroller(urlSerializer, transitions, viewportScroller, zone, config);
|
|
6995
7054
|
},
|
|
6996
7055
|
};
|
|
6997
7056
|
}
|
|
@@ -7049,7 +7108,7 @@ function provideRouterInitializer() {
|
|
|
7049
7108
|
/**
|
|
7050
7109
|
* @publicApi
|
|
7051
7110
|
*/
|
|
7052
|
-
const VERSION = new Version('15.0.
|
|
7111
|
+
const VERSION = new Version('15.0.2');
|
|
7053
7112
|
|
|
7054
7113
|
/**
|
|
7055
7114
|
* @license
|