@angular/router 16.0.0-next.4 → 16.0.0-next.6
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/esm2022/src/apply_redirects.mjs +112 -0
- package/{esm2020 → esm2022}/src/components/empty_outlet.mjs +4 -4
- package/esm2022/src/create_url_tree.mjs +418 -0
- package/{esm2020 → esm2022}/src/directives/router_link.mjs +4 -4
- package/{esm2020 → esm2022}/src/directives/router_link_active.mjs +4 -4
- package/esm2022/src/directives/router_outlet.mjs +336 -0
- package/esm2022/src/index.mjs +30 -0
- package/esm2022/src/navigation_transition.mjs +397 -0
- package/esm2022/src/operators/activate_routes.mjs +192 -0
- package/{esm2020 → esm2022}/src/operators/check_guards.mjs +1 -1
- package/esm2022/src/operators/recognize.mjs +16 -0
- package/{esm2020 → esm2022}/src/page_title_strategy.mjs +7 -7
- package/esm2022/src/provide_router.mjs +507 -0
- package/esm2022/src/recognize.mjs +360 -0
- package/{esm2020 → esm2022}/src/route_reuse_strategy.mjs +7 -7
- package/esm2022/src/router.mjs +724 -0
- package/esm2022/src/router_config.mjs +18 -0
- package/esm2022/src/router_config_loader.mjs +132 -0
- package/esm2022/src/router_module.mjs +220 -0
- package/{esm2020 → esm2022}/src/router_outlet_context.mjs +4 -4
- package/esm2022/src/router_preloader.mjs +167 -0
- package/{esm2020 → esm2022}/src/router_scroller.mjs +4 -4
- package/esm2022/src/router_state.mjs +408 -0
- package/{esm2020 → esm2022}/src/url_handling_strategy.mjs +7 -7
- package/esm2022/src/url_tree.mjs +642 -0
- package/esm2022/src/utils/navigations.mjs +42 -0
- package/esm2022/src/utils/type_guards.mjs +54 -0
- package/{esm2020 → esm2022}/src/version.mjs +1 -1
- package/{esm2020 → esm2022}/testing/src/router_testing_harness.mjs +7 -7
- package/{esm2020 → esm2022}/testing/src/router_testing_module.mjs +10 -10
- package/{fesm2020 → fesm2022}/router.mjs +799 -787
- package/fesm2022/router.mjs.map +1 -0
- package/{fesm2020 → fesm2022}/testing.mjs +16 -16
- package/{fesm2020 → fesm2022}/testing.mjs.map +1 -1
- package/{fesm2020 → fesm2022}/upgrade.mjs +1 -1
- package/index.d.ts +92 -5
- package/package.json +14 -24
- package/testing/index.d.ts +1 -1
- package/upgrade/index.d.ts +1 -1
- package/esm2020/src/apply_redirects.mjs +0 -331
- package/esm2020/src/create_url_tree.mjs +0 -417
- package/esm2020/src/directives/router_outlet.mjs +0 -259
- package/esm2020/src/index.mjs +0 -30
- package/esm2020/src/navigation_transition.mjs +0 -399
- package/esm2020/src/operators/activate_routes.mjs +0 -177
- package/esm2020/src/operators/apply_redirects.mjs +0 -14
- package/esm2020/src/operators/recognize.mjs +0 -14
- package/esm2020/src/provide_router.mjs +0 -477
- package/esm2020/src/recognize.mjs +0 -270
- package/esm2020/src/router.mjs +0 -710
- package/esm2020/src/router_config.mjs +0 -19
- package/esm2020/src/router_config_loader.mjs +0 -131
- package/esm2020/src/router_module.mjs +0 -216
- package/esm2020/src/router_preloader.mjs +0 -167
- package/esm2020/src/router_state.mjs +0 -409
- package/esm2020/src/url_tree.mjs +0 -631
- package/esm2020/src/utils/navigations.mjs +0 -42
- package/esm2020/src/utils/type_guards.mjs +0 -54
- package/fesm2015/router.mjs +0 -7001
- package/fesm2015/router.mjs.map +0 -1
- package/fesm2015/testing.mjs +0 -270
- package/fesm2015/testing.mjs.map +0 -1
- package/fesm2015/upgrade.mjs +0 -146
- package/fesm2015/upgrade.mjs.map +0 -1
- package/fesm2020/router.mjs.map +0 -1
- /package/{esm2020 → esm2022}/index.mjs +0 -0
- /package/{esm2020 → esm2022}/public_api.mjs +0 -0
- /package/{esm2020 → esm2022}/router.mjs +0 -0
- /package/{esm2020 → esm2022}/src/create_router_state.mjs +0 -0
- /package/{esm2020 → esm2022}/src/errors.mjs +0 -0
- /package/{esm2020 → esm2022}/src/events.mjs +0 -0
- /package/{esm2020 → esm2022}/src/models.mjs +0 -0
- /package/{esm2020 → esm2022}/src/models_deprecated.mjs +0 -0
- /package/{esm2020 → esm2022}/src/navigation_canceling_error.mjs +0 -0
- /package/{esm2020 → esm2022}/src/operators/prioritized_guard_value.mjs +0 -0
- /package/{esm2020 → esm2022}/src/operators/resolve_data.mjs +0 -0
- /package/{esm2020 → esm2022}/src/operators/switch_tap.mjs +0 -0
- /package/{esm2020 → esm2022}/src/private_export.mjs +0 -0
- /package/{esm2020 → esm2022}/src/shared.mjs +0 -0
- /package/{esm2020 → esm2022}/src/utils/collection.mjs +0 -0
- /package/{esm2020 → esm2022}/src/utils/config.mjs +0 -0
- /package/{esm2020 → esm2022}/src/utils/config_matching.mjs +0 -0
- /package/{esm2020 → esm2022}/src/utils/functional_guards.mjs +0 -0
- /package/{esm2020 → esm2022}/src/utils/preactivation.mjs +0 -0
- /package/{esm2020 → esm2022}/src/utils/tree.mjs +0 -0
- /package/{esm2020 → esm2022}/testing/index.mjs +0 -0
- /package/{esm2020 → esm2022}/testing/public_api.mjs +0 -0
- /package/{esm2020 → esm2022}/testing/src/testing.mjs +0 -0
- /package/{esm2020 → esm2022}/testing/testing.mjs +0 -0
- /package/{esm2020 → esm2022}/upgrade/index.mjs +0 -0
- /package/{esm2020 → esm2022}/upgrade/public_api.mjs +0 -0
- /package/{esm2020 → esm2022}/upgrade/src/upgrade.mjs +0 -0
- /package/{esm2020 → esm2022}/upgrade/upgrade.mjs +0 -0
- /package/{fesm2020 → fesm2022}/upgrade.mjs.map +0 -0
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular v16.0.0-next.
|
|
2
|
+
* @license Angular v16.0.0-next.6
|
|
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 { ɵisPromise, ɵRuntimeError, Injectable, EventEmitter, inject, ViewContainerRef, ChangeDetectorRef, EnvironmentInjector, Directive, Input, Output, Component, createEnvironmentInjector, ɵisNgModule, isStandalone, ɵisInjectable,
|
|
9
|
-
import { isObservable, from, of, BehaviorSubject,
|
|
8
|
+
import { ɵisPromise, ɵRuntimeError, Injectable, EventEmitter, inject, ViewContainerRef, ChangeDetectorRef, EnvironmentInjector, Directive, Input, Output, InjectionToken, reflectComponentType, Component, createEnvironmentInjector, ɵisNgModule, isStandalone, ɵisInjectable, Compiler, InjectFlags, NgModuleFactory, ɵConsole, ɵInitialRenderPendingTasks, NgZone, ɵcoerceToBoolean, ɵɵsanitizeUrlOrResourceUrl, Attribute, HostBinding, HostListener, Optional, ContentChildren, makeEnvironmentProviders, APP_BOOTSTRAP_LISTENER, ENVIRONMENT_INITIALIZER, Injector, ApplicationRef, APP_INITIALIZER, NgProbeToken, SkipSelf, NgModule, Inject, Version } from '@angular/core';
|
|
9
|
+
import { isObservable, from, of, BehaviorSubject, combineLatest, EmptyError, concat, defer, pipe, throwError, 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';
|
|
12
|
-
import { map, switchMap, take, startWith, filter, mergeMap, first, concatMap, tap, catchError, scan, last as last$1,
|
|
12
|
+
import { map, switchMap, take, startWith, filter, mergeMap, first, concatMap, tap, catchError, scan, defaultIfEmpty, last as last$1, takeLast, mapTo, finalize, refCount, mergeAll } from 'rxjs/operators';
|
|
13
13
|
import * as i1 from '@angular/platform-browser';
|
|
14
14
|
|
|
15
15
|
/**
|
|
@@ -162,7 +162,6 @@ function wrapIntoObservable(value) {
|
|
|
162
162
|
return of(value);
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
-
const NG_DEV_MODE$a = typeof ngDevMode === 'undefined' || ngDevMode;
|
|
166
165
|
const pathCompareMap = {
|
|
167
166
|
'exact': equalSegmentGroups,
|
|
168
167
|
'subset': containsSegmentGroup,
|
|
@@ -287,7 +286,7 @@ class UrlTree {
|
|
|
287
286
|
this.root = root;
|
|
288
287
|
this.queryParams = queryParams;
|
|
289
288
|
this.fragment = fragment;
|
|
290
|
-
if (
|
|
289
|
+
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
291
290
|
if (root.segments.length > 0) {
|
|
292
291
|
throw new ɵRuntimeError(4015 /* RuntimeErrorCode.INVALID_ROOT_URL_SEGMENT */, 'The root `UrlSegmentGroup` should not contain `segments`. ' +
|
|
293
292
|
'Instead, these segments belong in the `children` so they can be associated with a named outlet.');
|
|
@@ -420,10 +419,10 @@ function mapChildrenIntoArray(segment, fn) {
|
|
|
420
419
|
* @publicApi
|
|
421
420
|
*/
|
|
422
421
|
class UrlSerializer {
|
|
422
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: UrlSerializer, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
423
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: UrlSerializer, providedIn: 'root', useFactory: () => new DefaultUrlSerializer() }); }
|
|
423
424
|
}
|
|
424
|
-
|
|
425
|
-
UrlSerializer.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.0-next.4", ngImport: i0, type: UrlSerializer, providedIn: 'root', useFactory: () => new DefaultUrlSerializer() });
|
|
426
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.4", ngImport: i0, type: UrlSerializer, decorators: [{
|
|
425
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: UrlSerializer, decorators: [{
|
|
427
426
|
type: Injectable,
|
|
428
427
|
args: [{ providedIn: 'root', useFactory: () => new DefaultUrlSerializer() }]
|
|
429
428
|
}] });
|
|
@@ -635,7 +634,8 @@ class UrlParser {
|
|
|
635
634
|
parseSegment() {
|
|
636
635
|
const path = matchSegments(this.remaining);
|
|
637
636
|
if (path === '' && this.peekStartsWith(';')) {
|
|
638
|
-
throw new ɵRuntimeError(4009 /* RuntimeErrorCode.EMPTY_PATH_WITH_PARAMS */,
|
|
637
|
+
throw new ɵRuntimeError(4009 /* RuntimeErrorCode.EMPTY_PATH_WITH_PARAMS */, (typeof ngDevMode === 'undefined' || ngDevMode) &&
|
|
638
|
+
`Empty path url segment cannot have parameters: '${this.remaining}'.`);
|
|
639
639
|
}
|
|
640
640
|
this.capture(path);
|
|
641
641
|
return new UrlSegment(decode(path), this.parseMatrixParams());
|
|
@@ -704,7 +704,7 @@ class UrlParser {
|
|
|
704
704
|
// if is is not one of these characters, then the segment was unescaped
|
|
705
705
|
// or the group was not closed
|
|
706
706
|
if (next !== '/' && next !== ')' && next !== ';') {
|
|
707
|
-
throw new ɵRuntimeError(4010 /* RuntimeErrorCode.UNPARSABLE_URL */,
|
|
707
|
+
throw new ɵRuntimeError(4010 /* RuntimeErrorCode.UNPARSABLE_URL */, (typeof ngDevMode === 'undefined' || ngDevMode) && `Cannot parse url '${this.url}'`);
|
|
708
708
|
}
|
|
709
709
|
let outletName = undefined;
|
|
710
710
|
if (path.indexOf(':') > -1) {
|
|
@@ -735,7 +735,7 @@ class UrlParser {
|
|
|
735
735
|
}
|
|
736
736
|
capture(str) {
|
|
737
737
|
if (!this.consumeOptional(str)) {
|
|
738
|
-
throw new ɵRuntimeError(4011 /* RuntimeErrorCode.UNEXPECTED_VALUE_IN_URL */,
|
|
738
|
+
throw new ɵRuntimeError(4011 /* RuntimeErrorCode.UNEXPECTED_VALUE_IN_URL */, (typeof ngDevMode === 'undefined' || ngDevMode) && `Expected "${str}".`);
|
|
739
739
|
}
|
|
740
740
|
}
|
|
741
741
|
}
|
|
@@ -745,17 +745,28 @@ function createRoot(rootCandidate) {
|
|
|
745
745
|
rootCandidate;
|
|
746
746
|
}
|
|
747
747
|
/**
|
|
748
|
-
* Recursively
|
|
749
|
-
*
|
|
750
|
-
*
|
|
748
|
+
* Recursively
|
|
749
|
+
* - merges primary segment children into their parents
|
|
750
|
+
* - drops empty children (those which have no segments and no children themselves). This latter
|
|
751
|
+
* prevents serializing a group into something like `/a(aux:)`, where `aux` is an empty child
|
|
752
|
+
* segment.
|
|
753
|
+
* - merges named outlets without a primary segment sibling into the children. This prevents
|
|
754
|
+
* serializing a URL like `//(a:a)(b:b) instead of `/(a:a//b:b)` when the aux b route lives on the
|
|
755
|
+
* root but the `a` route lives under an empty path primary route.
|
|
751
756
|
*/
|
|
752
757
|
function squashSegmentGroup(segmentGroup) {
|
|
753
758
|
const newChildren = {};
|
|
754
759
|
for (const childOutlet of Object.keys(segmentGroup.children)) {
|
|
755
760
|
const child = segmentGroup.children[childOutlet];
|
|
756
761
|
const childCandidate = squashSegmentGroup(child);
|
|
757
|
-
//
|
|
758
|
-
if (childCandidate.segments.length
|
|
762
|
+
// moves named children in an empty path primary child into this group
|
|
763
|
+
if (childOutlet === PRIMARY_OUTLET && childCandidate.segments.length === 0 &&
|
|
764
|
+
childCandidate.hasChildren()) {
|
|
765
|
+
for (const [grandChildOutlet, grandChild] of Object.entries(childCandidate.children)) {
|
|
766
|
+
newChildren[grandChildOutlet] = grandChild;
|
|
767
|
+
}
|
|
768
|
+
} // don't add empty children
|
|
769
|
+
else if (childCandidate.segments.length > 0 || childCandidate.hasChildren()) {
|
|
759
770
|
newChildren[childOutlet] = childCandidate;
|
|
760
771
|
}
|
|
761
772
|
}
|
|
@@ -781,7 +792,6 @@ function isUrlTree(v) {
|
|
|
781
792
|
return v instanceof UrlTree;
|
|
782
793
|
}
|
|
783
794
|
|
|
784
|
-
const NG_DEV_MODE$9 = typeof ngDevMode === 'undefined' || ngDevMode;
|
|
785
795
|
/**
|
|
786
796
|
* Creates a `UrlTree` relative to an `ActivatedRouteSnapshot`.
|
|
787
797
|
*
|
|
@@ -928,11 +938,13 @@ class Navigation {
|
|
|
928
938
|
this.numberOfDoubleDots = numberOfDoubleDots;
|
|
929
939
|
this.commands = commands;
|
|
930
940
|
if (isAbsolute && commands.length > 0 && isMatrixParams(commands[0])) {
|
|
931
|
-
throw new ɵRuntimeError(4003 /* RuntimeErrorCode.ROOT_SEGMENT_MATRIX_PARAMS */,
|
|
941
|
+
throw new ɵRuntimeError(4003 /* RuntimeErrorCode.ROOT_SEGMENT_MATRIX_PARAMS */, (typeof ngDevMode === 'undefined' || ngDevMode) &&
|
|
942
|
+
'Root segment cannot have matrix parameters');
|
|
932
943
|
}
|
|
933
944
|
const cmdWithOutlet = commands.find(isCommandWithOutlets);
|
|
934
945
|
if (cmdWithOutlet && cmdWithOutlet !== last(commands)) {
|
|
935
|
-
throw new ɵRuntimeError(4004 /* RuntimeErrorCode.MISPLACED_OUTLETS_COMMAND */,
|
|
946
|
+
throw new ɵRuntimeError(4004 /* RuntimeErrorCode.MISPLACED_OUTLETS_COMMAND */, (typeof ngDevMode === 'undefined' || ngDevMode) &&
|
|
947
|
+
'{outlets:{}} has to be the last command');
|
|
936
948
|
}
|
|
937
949
|
}
|
|
938
950
|
toRoot() {
|
|
@@ -1016,7 +1028,7 @@ function createPositionApplyingDoubleDots(group, index, numberOfDoubleDots) {
|
|
|
1016
1028
|
dd -= ci;
|
|
1017
1029
|
g = g.parent;
|
|
1018
1030
|
if (!g) {
|
|
1019
|
-
throw new ɵRuntimeError(4005 /* RuntimeErrorCode.INVALID_DOUBLE_DOTS */,
|
|
1031
|
+
throw new ɵRuntimeError(4005 /* RuntimeErrorCode.INVALID_DOUBLE_DOTS */, (typeof ngDevMode === 'undefined' || ngDevMode) && 'Invalid number of \'../\'');
|
|
1020
1032
|
}
|
|
1021
1033
|
ci = g.segments.length;
|
|
1022
1034
|
}
|
|
@@ -1688,6 +1700,79 @@ function stringifyEvent(routerEvent) {
|
|
|
1688
1700
|
}
|
|
1689
1701
|
}
|
|
1690
1702
|
|
|
1703
|
+
/**
|
|
1704
|
+
* Store contextual information about a `RouterOutlet`
|
|
1705
|
+
*
|
|
1706
|
+
* @publicApi
|
|
1707
|
+
*/
|
|
1708
|
+
class OutletContext {
|
|
1709
|
+
constructor() {
|
|
1710
|
+
this.outlet = null;
|
|
1711
|
+
this.route = null;
|
|
1712
|
+
this.injector = null;
|
|
1713
|
+
this.children = new ChildrenOutletContexts();
|
|
1714
|
+
this.attachRef = null;
|
|
1715
|
+
}
|
|
1716
|
+
}
|
|
1717
|
+
/**
|
|
1718
|
+
* Store contextual information about the children (= nested) `RouterOutlet`
|
|
1719
|
+
*
|
|
1720
|
+
* @publicApi
|
|
1721
|
+
*/
|
|
1722
|
+
class ChildrenOutletContexts {
|
|
1723
|
+
constructor() {
|
|
1724
|
+
// contexts for child outlets, by name.
|
|
1725
|
+
this.contexts = new Map();
|
|
1726
|
+
}
|
|
1727
|
+
/** Called when a `RouterOutlet` directive is instantiated */
|
|
1728
|
+
onChildOutletCreated(childName, outlet) {
|
|
1729
|
+
const context = this.getOrCreateContext(childName);
|
|
1730
|
+
context.outlet = outlet;
|
|
1731
|
+
this.contexts.set(childName, context);
|
|
1732
|
+
}
|
|
1733
|
+
/**
|
|
1734
|
+
* Called when a `RouterOutlet` directive is destroyed.
|
|
1735
|
+
* We need to keep the context as the outlet could be destroyed inside a NgIf and might be
|
|
1736
|
+
* re-created later.
|
|
1737
|
+
*/
|
|
1738
|
+
onChildOutletDestroyed(childName) {
|
|
1739
|
+
const context = this.getContext(childName);
|
|
1740
|
+
if (context) {
|
|
1741
|
+
context.outlet = null;
|
|
1742
|
+
context.attachRef = null;
|
|
1743
|
+
}
|
|
1744
|
+
}
|
|
1745
|
+
/**
|
|
1746
|
+
* Called when the corresponding route is deactivated during navigation.
|
|
1747
|
+
* Because the component get destroyed, all children outlet are destroyed.
|
|
1748
|
+
*/
|
|
1749
|
+
onOutletDeactivated() {
|
|
1750
|
+
const contexts = this.contexts;
|
|
1751
|
+
this.contexts = new Map();
|
|
1752
|
+
return contexts;
|
|
1753
|
+
}
|
|
1754
|
+
onOutletReAttached(contexts) {
|
|
1755
|
+
this.contexts = contexts;
|
|
1756
|
+
}
|
|
1757
|
+
getOrCreateContext(childName) {
|
|
1758
|
+
let context = this.getContext(childName);
|
|
1759
|
+
if (!context) {
|
|
1760
|
+
context = new OutletContext();
|
|
1761
|
+
this.contexts.set(childName, context);
|
|
1762
|
+
}
|
|
1763
|
+
return context;
|
|
1764
|
+
}
|
|
1765
|
+
getContext(childName) {
|
|
1766
|
+
return this.contexts.get(childName) || null;
|
|
1767
|
+
}
|
|
1768
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: ChildrenOutletContexts, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1769
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: ChildrenOutletContexts, providedIn: 'root' }); }
|
|
1770
|
+
}
|
|
1771
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: ChildrenOutletContexts, decorators: [{
|
|
1772
|
+
type: Injectable,
|
|
1773
|
+
args: [{ providedIn: 'root' }]
|
|
1774
|
+
}] });
|
|
1775
|
+
|
|
1691
1776
|
class Tree {
|
|
1692
1777
|
constructor(root) {
|
|
1693
1778
|
this._root = root;
|
|
@@ -1881,9 +1966,8 @@ class ActivatedRoute {
|
|
|
1881
1966
|
this.data = data;
|
|
1882
1967
|
this.outlet = outlet;
|
|
1883
1968
|
this.component = component;
|
|
1884
|
-
/** An Observable of the resolved route title */
|
|
1885
|
-
this.title = this.data?.pipe(map((d) => d[RouteTitleKey])) ?? of(undefined);
|
|
1886
1969
|
this._futureSnapshot = futureSnapshot;
|
|
1970
|
+
this.title = this.data?.pipe(map((d) => d[RouteTitleKey])) ?? of(undefined);
|
|
1887
1971
|
}
|
|
1888
1972
|
/** The configuration used to match this route. */
|
|
1889
1973
|
get routeConfig() {
|
|
@@ -2171,146 +2255,6 @@ function equalParamsAndUrlSegments(a, b) {
|
|
|
2171
2255
|
(!a.parent || equalParamsAndUrlSegments(a.parent, b.parent));
|
|
2172
2256
|
}
|
|
2173
2257
|
|
|
2174
|
-
function createRouterState(routeReuseStrategy, curr, prevState) {
|
|
2175
|
-
const root = createNode(routeReuseStrategy, curr._root, prevState ? prevState._root : undefined);
|
|
2176
|
-
return new RouterState(root, curr);
|
|
2177
|
-
}
|
|
2178
|
-
function createNode(routeReuseStrategy, curr, prevState) {
|
|
2179
|
-
// reuse an activated route that is currently displayed on the screen
|
|
2180
|
-
if (prevState && routeReuseStrategy.shouldReuseRoute(curr.value, prevState.value.snapshot)) {
|
|
2181
|
-
const value = prevState.value;
|
|
2182
|
-
value._futureSnapshot = curr.value;
|
|
2183
|
-
const children = createOrReuseChildren(routeReuseStrategy, curr, prevState);
|
|
2184
|
-
return new TreeNode(value, children);
|
|
2185
|
-
}
|
|
2186
|
-
else {
|
|
2187
|
-
if (routeReuseStrategy.shouldAttach(curr.value)) {
|
|
2188
|
-
// retrieve an activated route that is used to be displayed, but is not currently displayed
|
|
2189
|
-
const detachedRouteHandle = routeReuseStrategy.retrieve(curr.value);
|
|
2190
|
-
if (detachedRouteHandle !== null) {
|
|
2191
|
-
const tree = detachedRouteHandle.route;
|
|
2192
|
-
tree.value._futureSnapshot = curr.value;
|
|
2193
|
-
tree.children = curr.children.map(c => createNode(routeReuseStrategy, c));
|
|
2194
|
-
return tree;
|
|
2195
|
-
}
|
|
2196
|
-
}
|
|
2197
|
-
const value = createActivatedRoute(curr.value);
|
|
2198
|
-
const children = curr.children.map(c => createNode(routeReuseStrategy, c));
|
|
2199
|
-
return new TreeNode(value, children);
|
|
2200
|
-
}
|
|
2201
|
-
}
|
|
2202
|
-
function createOrReuseChildren(routeReuseStrategy, curr, prevState) {
|
|
2203
|
-
return curr.children.map(child => {
|
|
2204
|
-
for (const p of prevState.children) {
|
|
2205
|
-
if (routeReuseStrategy.shouldReuseRoute(child.value, p.value.snapshot)) {
|
|
2206
|
-
return createNode(routeReuseStrategy, child, p);
|
|
2207
|
-
}
|
|
2208
|
-
}
|
|
2209
|
-
return createNode(routeReuseStrategy, child);
|
|
2210
|
-
});
|
|
2211
|
-
}
|
|
2212
|
-
function createActivatedRoute(c) {
|
|
2213
|
-
return new ActivatedRoute(new BehaviorSubject(c.url), new BehaviorSubject(c.params), new BehaviorSubject(c.queryParams), new BehaviorSubject(c.fragment), new BehaviorSubject(c.data), c.outlet, c.component, c);
|
|
2214
|
-
}
|
|
2215
|
-
|
|
2216
|
-
const NAVIGATION_CANCELING_ERROR = 'ngNavigationCancelingError';
|
|
2217
|
-
function redirectingNavigationError(urlSerializer, redirect) {
|
|
2218
|
-
const { redirectTo, navigationBehaviorOptions } = isUrlTree(redirect) ? { redirectTo: redirect, navigationBehaviorOptions: undefined } : redirect;
|
|
2219
|
-
const error = navigationCancelingError(ngDevMode && `Redirecting to "${urlSerializer.serialize(redirectTo)}"`, 0 /* NavigationCancellationCode.Redirect */, redirect);
|
|
2220
|
-
error.url = redirectTo;
|
|
2221
|
-
error.navigationBehaviorOptions = navigationBehaviorOptions;
|
|
2222
|
-
return error;
|
|
2223
|
-
}
|
|
2224
|
-
function navigationCancelingError(message, code, redirectUrl) {
|
|
2225
|
-
const error = new Error('NavigationCancelingError: ' + (message || ''));
|
|
2226
|
-
error[NAVIGATION_CANCELING_ERROR] = true;
|
|
2227
|
-
error.cancellationCode = code;
|
|
2228
|
-
if (redirectUrl) {
|
|
2229
|
-
error.url = redirectUrl;
|
|
2230
|
-
}
|
|
2231
|
-
return error;
|
|
2232
|
-
}
|
|
2233
|
-
function isRedirectingNavigationCancelingError$1(error) {
|
|
2234
|
-
return isNavigationCancelingError$1(error) && isUrlTree(error.url);
|
|
2235
|
-
}
|
|
2236
|
-
function isNavigationCancelingError$1(error) {
|
|
2237
|
-
return error && error[NAVIGATION_CANCELING_ERROR];
|
|
2238
|
-
}
|
|
2239
|
-
|
|
2240
|
-
/**
|
|
2241
|
-
* Store contextual information about a `RouterOutlet`
|
|
2242
|
-
*
|
|
2243
|
-
* @publicApi
|
|
2244
|
-
*/
|
|
2245
|
-
class OutletContext {
|
|
2246
|
-
constructor() {
|
|
2247
|
-
this.outlet = null;
|
|
2248
|
-
this.route = null;
|
|
2249
|
-
this.injector = null;
|
|
2250
|
-
this.children = new ChildrenOutletContexts();
|
|
2251
|
-
this.attachRef = null;
|
|
2252
|
-
}
|
|
2253
|
-
}
|
|
2254
|
-
/**
|
|
2255
|
-
* Store contextual information about the children (= nested) `RouterOutlet`
|
|
2256
|
-
*
|
|
2257
|
-
* @publicApi
|
|
2258
|
-
*/
|
|
2259
|
-
class ChildrenOutletContexts {
|
|
2260
|
-
constructor() {
|
|
2261
|
-
// contexts for child outlets, by name.
|
|
2262
|
-
this.contexts = new Map();
|
|
2263
|
-
}
|
|
2264
|
-
/** Called when a `RouterOutlet` directive is instantiated */
|
|
2265
|
-
onChildOutletCreated(childName, outlet) {
|
|
2266
|
-
const context = this.getOrCreateContext(childName);
|
|
2267
|
-
context.outlet = outlet;
|
|
2268
|
-
this.contexts.set(childName, context);
|
|
2269
|
-
}
|
|
2270
|
-
/**
|
|
2271
|
-
* Called when a `RouterOutlet` directive is destroyed.
|
|
2272
|
-
* We need to keep the context as the outlet could be destroyed inside a NgIf and might be
|
|
2273
|
-
* re-created later.
|
|
2274
|
-
*/
|
|
2275
|
-
onChildOutletDestroyed(childName) {
|
|
2276
|
-
const context = this.getContext(childName);
|
|
2277
|
-
if (context) {
|
|
2278
|
-
context.outlet = null;
|
|
2279
|
-
context.attachRef = null;
|
|
2280
|
-
}
|
|
2281
|
-
}
|
|
2282
|
-
/**
|
|
2283
|
-
* Called when the corresponding route is deactivated during navigation.
|
|
2284
|
-
* Because the component get destroyed, all children outlet are destroyed.
|
|
2285
|
-
*/
|
|
2286
|
-
onOutletDeactivated() {
|
|
2287
|
-
const contexts = this.contexts;
|
|
2288
|
-
this.contexts = new Map();
|
|
2289
|
-
return contexts;
|
|
2290
|
-
}
|
|
2291
|
-
onOutletReAttached(contexts) {
|
|
2292
|
-
this.contexts = contexts;
|
|
2293
|
-
}
|
|
2294
|
-
getOrCreateContext(childName) {
|
|
2295
|
-
let context = this.getContext(childName);
|
|
2296
|
-
if (!context) {
|
|
2297
|
-
context = new OutletContext();
|
|
2298
|
-
this.contexts.set(childName, context);
|
|
2299
|
-
}
|
|
2300
|
-
return context;
|
|
2301
|
-
}
|
|
2302
|
-
getContext(childName) {
|
|
2303
|
-
return this.contexts.get(childName) || null;
|
|
2304
|
-
}
|
|
2305
|
-
}
|
|
2306
|
-
ChildrenOutletContexts.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0-next.4", ngImport: i0, type: ChildrenOutletContexts, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2307
|
-
ChildrenOutletContexts.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.0-next.4", ngImport: i0, type: ChildrenOutletContexts, providedIn: 'root' });
|
|
2308
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.4", ngImport: i0, type: ChildrenOutletContexts, decorators: [{
|
|
2309
|
-
type: Injectable,
|
|
2310
|
-
args: [{ providedIn: 'root' }]
|
|
2311
|
-
}] });
|
|
2312
|
-
|
|
2313
|
-
const NG_DEV_MODE$8 = typeof ngDevMode === 'undefined' || ngDevMode;
|
|
2314
2258
|
/**
|
|
2315
2259
|
* @description
|
|
2316
2260
|
*
|
|
@@ -2388,6 +2332,13 @@ class RouterOutlet {
|
|
|
2388
2332
|
this.location = inject(ViewContainerRef);
|
|
2389
2333
|
this.changeDetector = inject(ChangeDetectorRef);
|
|
2390
2334
|
this.environmentInjector = inject(EnvironmentInjector);
|
|
2335
|
+
this.inputBinder = inject(INPUT_BINDER, { optional: true });
|
|
2336
|
+
/** @nodoc */
|
|
2337
|
+
this.supportsBindingToComponentInputs = true;
|
|
2338
|
+
}
|
|
2339
|
+
/** @internal */
|
|
2340
|
+
get activatedComponentRef() {
|
|
2341
|
+
return this.activated;
|
|
2391
2342
|
}
|
|
2392
2343
|
/** @nodoc */
|
|
2393
2344
|
ngOnChanges(changes) {
|
|
@@ -2413,6 +2364,7 @@ class RouterOutlet {
|
|
|
2413
2364
|
if (this.isTrackedInParentContexts(this.name)) {
|
|
2414
2365
|
this.parentContexts.onChildOutletDestroyed(this.name);
|
|
2415
2366
|
}
|
|
2367
|
+
this.inputBinder?.unsubscribeFromRouteData(this);
|
|
2416
2368
|
}
|
|
2417
2369
|
isTrackedInParentContexts(outletName) {
|
|
2418
2370
|
return this.parentContexts.getContext(outletName)?.outlet === this;
|
|
@@ -2449,12 +2401,12 @@ class RouterOutlet {
|
|
|
2449
2401
|
*/
|
|
2450
2402
|
get component() {
|
|
2451
2403
|
if (!this.activated)
|
|
2452
|
-
throw new ɵRuntimeError(4012 /* RuntimeErrorCode.OUTLET_NOT_ACTIVATED */,
|
|
2404
|
+
throw new ɵRuntimeError(4012 /* RuntimeErrorCode.OUTLET_NOT_ACTIVATED */, (typeof ngDevMode === 'undefined' || ngDevMode) && 'Outlet is not activated');
|
|
2453
2405
|
return this.activated.instance;
|
|
2454
2406
|
}
|
|
2455
2407
|
get activatedRoute() {
|
|
2456
2408
|
if (!this.activated)
|
|
2457
|
-
throw new ɵRuntimeError(4012 /* RuntimeErrorCode.OUTLET_NOT_ACTIVATED */,
|
|
2409
|
+
throw new ɵRuntimeError(4012 /* RuntimeErrorCode.OUTLET_NOT_ACTIVATED */, (typeof ngDevMode === 'undefined' || ngDevMode) && 'Outlet is not activated');
|
|
2458
2410
|
return this._activatedRoute;
|
|
2459
2411
|
}
|
|
2460
2412
|
get activatedRouteData() {
|
|
@@ -2468,7 +2420,7 @@ class RouterOutlet {
|
|
|
2468
2420
|
*/
|
|
2469
2421
|
detach() {
|
|
2470
2422
|
if (!this.activated)
|
|
2471
|
-
throw new ɵRuntimeError(4012 /* RuntimeErrorCode.OUTLET_NOT_ACTIVATED */,
|
|
2423
|
+
throw new ɵRuntimeError(4012 /* RuntimeErrorCode.OUTLET_NOT_ACTIVATED */, (typeof ngDevMode === 'undefined' || ngDevMode) && 'Outlet is not activated');
|
|
2472
2424
|
this.location.detach();
|
|
2473
2425
|
const cmp = this.activated;
|
|
2474
2426
|
this.activated = null;
|
|
@@ -2483,6 +2435,7 @@ class RouterOutlet {
|
|
|
2483
2435
|
this.activated = ref;
|
|
2484
2436
|
this._activatedRoute = activatedRoute;
|
|
2485
2437
|
this.location.insert(ref.hostView);
|
|
2438
|
+
this.inputBinder?.bindActivatedRouteToOutletComponent(this);
|
|
2486
2439
|
this.attachEvents.emit(ref.instance);
|
|
2487
2440
|
}
|
|
2488
2441
|
deactivate() {
|
|
@@ -2496,7 +2449,8 @@ class RouterOutlet {
|
|
|
2496
2449
|
}
|
|
2497
2450
|
activateWith(activatedRoute, environmentInjector) {
|
|
2498
2451
|
if (this.isActivated) {
|
|
2499
|
-
throw new ɵRuntimeError(4013 /* RuntimeErrorCode.OUTLET_ALREADY_ACTIVATED */,
|
|
2452
|
+
throw new ɵRuntimeError(4013 /* RuntimeErrorCode.OUTLET_ALREADY_ACTIVATED */, (typeof ngDevMode === 'undefined' || ngDevMode) &&
|
|
2453
|
+
'Cannot activate an already activated outlet');
|
|
2500
2454
|
}
|
|
2501
2455
|
this._activatedRoute = activatedRoute;
|
|
2502
2456
|
const location = this.location;
|
|
@@ -2512,12 +2466,13 @@ class RouterOutlet {
|
|
|
2512
2466
|
// Calling `markForCheck` to make sure we will run the change detection when the
|
|
2513
2467
|
// `RouterOutlet` is inside a `ChangeDetectionStrategy.OnPush` component.
|
|
2514
2468
|
this.changeDetector.markForCheck();
|
|
2469
|
+
this.inputBinder?.bindActivatedRouteToOutletComponent(this);
|
|
2515
2470
|
this.activateEvents.emit(this.activated.instance);
|
|
2516
2471
|
}
|
|
2472
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: RouterOutlet, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
2473
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.0-next.6", 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 }); }
|
|
2517
2474
|
}
|
|
2518
|
-
|
|
2519
|
-
RouterOutlet.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.0-next.4", 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 });
|
|
2520
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.4", ngImport: i0, type: RouterOutlet, decorators: [{
|
|
2475
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: RouterOutlet, decorators: [{
|
|
2521
2476
|
type: Directive,
|
|
2522
2477
|
args: [{
|
|
2523
2478
|
selector: 'router-outlet',
|
|
@@ -2555,48 +2510,178 @@ class OutletInjector {
|
|
|
2555
2510
|
return this.parent.get(token, notFoundValue);
|
|
2556
2511
|
}
|
|
2557
2512
|
}
|
|
2558
|
-
|
|
2513
|
+
const INPUT_BINDER = new InjectionToken('');
|
|
2559
2514
|
/**
|
|
2560
|
-
*
|
|
2561
|
-
*
|
|
2562
|
-
*
|
|
2563
|
-
*
|
|
2564
|
-
*
|
|
2565
|
-
*
|
|
2566
|
-
*
|
|
2515
|
+
* Injectable used as a tree-shakable provider for opting in to binding router data to component
|
|
2516
|
+
* inputs.
|
|
2517
|
+
*
|
|
2518
|
+
* The RouterOutlet registers itself with this service when an `ActivatedRoute` is attached or
|
|
2519
|
+
* activated. When this happens, the service subscribes to the `ActivatedRoute` observables (params,
|
|
2520
|
+
* queryParams, data) and sets the inputs of the component using `ComponentRef.setInput`.
|
|
2521
|
+
* Importantly, when an input does not have an item in the route data with a matching key, this
|
|
2522
|
+
* input is set to `undefined`. If it were not done this way, the previous information would be
|
|
2523
|
+
* retained if the data got removed from the route (i.e. if a query parameter is removed).
|
|
2524
|
+
*
|
|
2525
|
+
* The `RouterOutlet` should unregister itself when destroyed via `unsubscribeFromRouteData` so that
|
|
2526
|
+
* the subscriptions are cleaned up.
|
|
2567
2527
|
*/
|
|
2568
|
-
class
|
|
2528
|
+
class RoutedComponentInputBinder {
|
|
2529
|
+
constructor() {
|
|
2530
|
+
this.outletDataSubscriptions = new Map;
|
|
2531
|
+
}
|
|
2532
|
+
bindActivatedRouteToOutletComponent(outlet) {
|
|
2533
|
+
this.unsubscribeFromRouteData(outlet);
|
|
2534
|
+
this.subscribeToRouteData(outlet);
|
|
2535
|
+
}
|
|
2536
|
+
unsubscribeFromRouteData(outlet) {
|
|
2537
|
+
this.outletDataSubscriptions.get(outlet)?.unsubscribe();
|
|
2538
|
+
this.outletDataSubscriptions.delete(outlet);
|
|
2539
|
+
}
|
|
2540
|
+
subscribeToRouteData(outlet) {
|
|
2541
|
+
const { activatedRoute } = outlet;
|
|
2542
|
+
const dataSubscription = combineLatest([
|
|
2543
|
+
activatedRoute.queryParams,
|
|
2544
|
+
activatedRoute.params,
|
|
2545
|
+
activatedRoute.data,
|
|
2546
|
+
])
|
|
2547
|
+
.pipe(switchMap(([queryParams, params, data]) => {
|
|
2548
|
+
// Promise.resolve is used to avoid synchronously writing the wrong data when two of
|
|
2549
|
+
// the Observables in the `combineLatest` stream emit one after another.
|
|
2550
|
+
return Promise.resolve({ ...queryParams, ...params, ...data });
|
|
2551
|
+
}))
|
|
2552
|
+
.subscribe(data => {
|
|
2553
|
+
// Outlet may have been deactivated or changed names to be associated with a different
|
|
2554
|
+
// route
|
|
2555
|
+
if (!outlet.isActivated || !outlet.activatedComponentRef ||
|
|
2556
|
+
outlet.activatedRoute !== activatedRoute || activatedRoute.component === null) {
|
|
2557
|
+
this.unsubscribeFromRouteData(outlet);
|
|
2558
|
+
return;
|
|
2559
|
+
}
|
|
2560
|
+
const mirror = reflectComponentType(activatedRoute.component);
|
|
2561
|
+
if (!mirror) {
|
|
2562
|
+
this.unsubscribeFromRouteData(outlet);
|
|
2563
|
+
return;
|
|
2564
|
+
}
|
|
2565
|
+
for (const { templateName } of mirror.inputs) {
|
|
2566
|
+
outlet.activatedComponentRef.setInput(templateName, data[templateName]);
|
|
2567
|
+
}
|
|
2568
|
+
});
|
|
2569
|
+
this.outletDataSubscriptions.set(outlet, dataSubscription);
|
|
2570
|
+
}
|
|
2571
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: RoutedComponentInputBinder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2572
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: RoutedComponentInputBinder }); }
|
|
2569
2573
|
}
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.4", ngImport: i0, type: ɵEmptyOutletComponent, decorators: [{
|
|
2573
|
-
type: Component,
|
|
2574
|
-
args: [{
|
|
2575
|
-
template: `<router-outlet></router-outlet>`,
|
|
2576
|
-
imports: [RouterOutlet],
|
|
2577
|
-
standalone: true,
|
|
2578
|
-
}]
|
|
2574
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: RoutedComponentInputBinder, decorators: [{
|
|
2575
|
+
type: Injectable
|
|
2579
2576
|
}] });
|
|
2580
2577
|
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
* `currentInjector`.
|
|
2585
|
-
*
|
|
2586
|
-
* @param route The route that might have providers
|
|
2587
|
-
* @param currentInjector The parent injector of the `Route`
|
|
2588
|
-
*/
|
|
2589
|
-
function getOrCreateRouteInjectorIfNeeded(route, currentInjector) {
|
|
2590
|
-
if (route.providers && !route._injector) {
|
|
2591
|
-
route._injector =
|
|
2592
|
-
createEnvironmentInjector(route.providers, currentInjector, `Route: ${route.path}`);
|
|
2593
|
-
}
|
|
2594
|
-
return route._injector ?? currentInjector;
|
|
2595
|
-
}
|
|
2596
|
-
function getLoadedRoutes(route) {
|
|
2597
|
-
return route._loadedRoutes;
|
|
2578
|
+
function createRouterState(routeReuseStrategy, curr, prevState) {
|
|
2579
|
+
const root = createNode(routeReuseStrategy, curr._root, prevState ? prevState._root : undefined);
|
|
2580
|
+
return new RouterState(root, curr);
|
|
2598
2581
|
}
|
|
2599
|
-
function
|
|
2582
|
+
function createNode(routeReuseStrategy, curr, prevState) {
|
|
2583
|
+
// reuse an activated route that is currently displayed on the screen
|
|
2584
|
+
if (prevState && routeReuseStrategy.shouldReuseRoute(curr.value, prevState.value.snapshot)) {
|
|
2585
|
+
const value = prevState.value;
|
|
2586
|
+
value._futureSnapshot = curr.value;
|
|
2587
|
+
const children = createOrReuseChildren(routeReuseStrategy, curr, prevState);
|
|
2588
|
+
return new TreeNode(value, children);
|
|
2589
|
+
}
|
|
2590
|
+
else {
|
|
2591
|
+
if (routeReuseStrategy.shouldAttach(curr.value)) {
|
|
2592
|
+
// retrieve an activated route that is used to be displayed, but is not currently displayed
|
|
2593
|
+
const detachedRouteHandle = routeReuseStrategy.retrieve(curr.value);
|
|
2594
|
+
if (detachedRouteHandle !== null) {
|
|
2595
|
+
const tree = detachedRouteHandle.route;
|
|
2596
|
+
tree.value._futureSnapshot = curr.value;
|
|
2597
|
+
tree.children = curr.children.map(c => createNode(routeReuseStrategy, c));
|
|
2598
|
+
return tree;
|
|
2599
|
+
}
|
|
2600
|
+
}
|
|
2601
|
+
const value = createActivatedRoute(curr.value);
|
|
2602
|
+
const children = curr.children.map(c => createNode(routeReuseStrategy, c));
|
|
2603
|
+
return new TreeNode(value, children);
|
|
2604
|
+
}
|
|
2605
|
+
}
|
|
2606
|
+
function createOrReuseChildren(routeReuseStrategy, curr, prevState) {
|
|
2607
|
+
return curr.children.map(child => {
|
|
2608
|
+
for (const p of prevState.children) {
|
|
2609
|
+
if (routeReuseStrategy.shouldReuseRoute(child.value, p.value.snapshot)) {
|
|
2610
|
+
return createNode(routeReuseStrategy, child, p);
|
|
2611
|
+
}
|
|
2612
|
+
}
|
|
2613
|
+
return createNode(routeReuseStrategy, child);
|
|
2614
|
+
});
|
|
2615
|
+
}
|
|
2616
|
+
function createActivatedRoute(c) {
|
|
2617
|
+
return new ActivatedRoute(new BehaviorSubject(c.url), new BehaviorSubject(c.params), new BehaviorSubject(c.queryParams), new BehaviorSubject(c.fragment), new BehaviorSubject(c.data), c.outlet, c.component, c);
|
|
2618
|
+
}
|
|
2619
|
+
|
|
2620
|
+
const NAVIGATION_CANCELING_ERROR = 'ngNavigationCancelingError';
|
|
2621
|
+
function redirectingNavigationError(urlSerializer, redirect) {
|
|
2622
|
+
const { redirectTo, navigationBehaviorOptions } = isUrlTree(redirect) ? { redirectTo: redirect, navigationBehaviorOptions: undefined } : redirect;
|
|
2623
|
+
const error = navigationCancelingError(ngDevMode && `Redirecting to "${urlSerializer.serialize(redirectTo)}"`, 0 /* NavigationCancellationCode.Redirect */, redirect);
|
|
2624
|
+
error.url = redirectTo;
|
|
2625
|
+
error.navigationBehaviorOptions = navigationBehaviorOptions;
|
|
2626
|
+
return error;
|
|
2627
|
+
}
|
|
2628
|
+
function navigationCancelingError(message, code, redirectUrl) {
|
|
2629
|
+
const error = new Error('NavigationCancelingError: ' + (message || ''));
|
|
2630
|
+
error[NAVIGATION_CANCELING_ERROR] = true;
|
|
2631
|
+
error.cancellationCode = code;
|
|
2632
|
+
if (redirectUrl) {
|
|
2633
|
+
error.url = redirectUrl;
|
|
2634
|
+
}
|
|
2635
|
+
return error;
|
|
2636
|
+
}
|
|
2637
|
+
function isRedirectingNavigationCancelingError$1(error) {
|
|
2638
|
+
return isNavigationCancelingError$1(error) && isUrlTree(error.url);
|
|
2639
|
+
}
|
|
2640
|
+
function isNavigationCancelingError$1(error) {
|
|
2641
|
+
return error && error[NAVIGATION_CANCELING_ERROR];
|
|
2642
|
+
}
|
|
2643
|
+
|
|
2644
|
+
/**
|
|
2645
|
+
* This component is used internally within the router to be a placeholder when an empty
|
|
2646
|
+
* router-outlet is needed. For example, with a config such as:
|
|
2647
|
+
*
|
|
2648
|
+
* `{path: 'parent', outlet: 'nav', children: [...]}`
|
|
2649
|
+
*
|
|
2650
|
+
* In order to render, there needs to be a component on this config, which will default
|
|
2651
|
+
* to this `EmptyOutletComponent`.
|
|
2652
|
+
*/
|
|
2653
|
+
class ɵEmptyOutletComponent {
|
|
2654
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: ɵEmptyOutletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2655
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.0.0-next.6", 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"] }] }); }
|
|
2656
|
+
}
|
|
2657
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: ɵEmptyOutletComponent, decorators: [{
|
|
2658
|
+
type: Component,
|
|
2659
|
+
args: [{
|
|
2660
|
+
template: `<router-outlet></router-outlet>`,
|
|
2661
|
+
imports: [RouterOutlet],
|
|
2662
|
+
standalone: true,
|
|
2663
|
+
}]
|
|
2664
|
+
}] });
|
|
2665
|
+
|
|
2666
|
+
/**
|
|
2667
|
+
* Creates an `EnvironmentInjector` if the `Route` has providers and one does not already exist
|
|
2668
|
+
* and returns the injector. Otherwise, if the `Route` does not have `providers`, returns the
|
|
2669
|
+
* `currentInjector`.
|
|
2670
|
+
*
|
|
2671
|
+
* @param route The route that might have providers
|
|
2672
|
+
* @param currentInjector The parent injector of the `Route`
|
|
2673
|
+
*/
|
|
2674
|
+
function getOrCreateRouteInjectorIfNeeded(route, currentInjector) {
|
|
2675
|
+
if (route.providers && !route._injector) {
|
|
2676
|
+
route._injector =
|
|
2677
|
+
createEnvironmentInjector(route.providers, currentInjector, `Route: ${route.path}`);
|
|
2678
|
+
}
|
|
2679
|
+
return route._injector ?? currentInjector;
|
|
2680
|
+
}
|
|
2681
|
+
function getLoadedRoutes(route) {
|
|
2682
|
+
return route._loadedRoutes;
|
|
2683
|
+
}
|
|
2684
|
+
function getLoadedInjector(route) {
|
|
2600
2685
|
return route._loadedInjector;
|
|
2601
2686
|
}
|
|
2602
2687
|
function getLoadedComponent(route) {
|
|
@@ -2765,17 +2850,19 @@ function getClosestRouteInjector(snapshot) {
|
|
|
2765
2850
|
return null;
|
|
2766
2851
|
}
|
|
2767
2852
|
|
|
2768
|
-
|
|
2769
|
-
|
|
2853
|
+
let warnedAboutUnsupportedInputBinding = false;
|
|
2854
|
+
const activateRoutes = (rootContexts, routeReuseStrategy, forwardEvent, inputBindingEnabled) => map(t => {
|
|
2855
|
+
new ActivateRoutes(routeReuseStrategy, t.targetRouterState, t.currentRouterState, forwardEvent, inputBindingEnabled)
|
|
2770
2856
|
.activate(rootContexts);
|
|
2771
2857
|
return t;
|
|
2772
2858
|
});
|
|
2773
2859
|
class ActivateRoutes {
|
|
2774
|
-
constructor(routeReuseStrategy, futureState, currState, forwardEvent) {
|
|
2860
|
+
constructor(routeReuseStrategy, futureState, currState, forwardEvent, inputBindingEnabled) {
|
|
2775
2861
|
this.routeReuseStrategy = routeReuseStrategy;
|
|
2776
2862
|
this.futureState = futureState;
|
|
2777
2863
|
this.currState = currState;
|
|
2778
2864
|
this.forwardEvent = forwardEvent;
|
|
2865
|
+
this.inputBindingEnabled = inputBindingEnabled;
|
|
2779
2866
|
}
|
|
2780
2867
|
activate(parentContexts) {
|
|
2781
2868
|
const futureRoot = this.futureState._root;
|
|
@@ -2854,13 +2941,16 @@ class ActivateRoutes {
|
|
|
2854
2941
|
for (const childOutlet of Object.keys(children)) {
|
|
2855
2942
|
this.deactivateRouteAndItsChildren(children[childOutlet], contexts);
|
|
2856
2943
|
}
|
|
2857
|
-
if (context
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2944
|
+
if (context) {
|
|
2945
|
+
if (context.outlet) {
|
|
2946
|
+
// Destroy the component
|
|
2947
|
+
context.outlet.deactivate();
|
|
2948
|
+
// Destroy the contexts for all the outlets that were in the component
|
|
2949
|
+
context.children.onOutletDeactivated();
|
|
2950
|
+
}
|
|
2862
2951
|
// Clear the information about the attached component on the context but keep the reference to
|
|
2863
|
-
// the outlet.
|
|
2952
|
+
// the outlet. Clear even if outlet was not yet activated to avoid activating later with old
|
|
2953
|
+
// info
|
|
2864
2954
|
context.attachRef = null;
|
|
2865
2955
|
context.route = null;
|
|
2866
2956
|
}
|
|
@@ -2927,6 +3017,16 @@ class ActivateRoutes {
|
|
|
2927
3017
|
this.activateChildRoutes(futureNode, null, parentContexts);
|
|
2928
3018
|
}
|
|
2929
3019
|
}
|
|
3020
|
+
if ((typeof ngDevMode === 'undefined' || ngDevMode)) {
|
|
3021
|
+
const context = parentContexts.getOrCreateContext(future.outlet);
|
|
3022
|
+
const outlet = context.outlet;
|
|
3023
|
+
if (outlet && this.inputBindingEnabled && !outlet.supportsBindingToComponentInputs &&
|
|
3024
|
+
!warnedAboutUnsupportedInputBinding) {
|
|
3025
|
+
console.warn(`'withComponentInputBinding' feature is enabled but ` +
|
|
3026
|
+
`this application is using an outlet that may not support binding to component inputs.`);
|
|
3027
|
+
warnedAboutUnsupportedInputBinding = true;
|
|
3028
|
+
}
|
|
3029
|
+
}
|
|
2930
3030
|
}
|
|
2931
3031
|
}
|
|
2932
3032
|
|
|
@@ -3287,136 +3387,7 @@ function runCanMatchGuards(injector, route, segments, urlSerializer) {
|
|
|
3287
3387
|
.pipe(prioritizedGuardValue(), redirectIfUrlTree(urlSerializer));
|
|
3288
3388
|
}
|
|
3289
3389
|
|
|
3290
|
-
|
|
3291
|
-
matched: false,
|
|
3292
|
-
consumedSegments: [],
|
|
3293
|
-
remainingSegments: [],
|
|
3294
|
-
parameters: {},
|
|
3295
|
-
positionalParamSegments: {}
|
|
3296
|
-
};
|
|
3297
|
-
function matchWithChecks(segmentGroup, route, segments, injector, urlSerializer) {
|
|
3298
|
-
const result = match(segmentGroup, route, segments);
|
|
3299
|
-
if (!result.matched) {
|
|
3300
|
-
return of(result);
|
|
3301
|
-
}
|
|
3302
|
-
// Only create the Route's `EnvironmentInjector` if it matches the attempted
|
|
3303
|
-
// navigation
|
|
3304
|
-
injector = getOrCreateRouteInjectorIfNeeded(route, injector);
|
|
3305
|
-
return runCanMatchGuards(injector, route, segments, urlSerializer)
|
|
3306
|
-
.pipe(map((v) => v === true ? result : { ...noMatch$1 }));
|
|
3307
|
-
}
|
|
3308
|
-
function match(segmentGroup, route, segments) {
|
|
3309
|
-
if (route.path === '') {
|
|
3310
|
-
if (route.pathMatch === 'full' && (segmentGroup.hasChildren() || segments.length > 0)) {
|
|
3311
|
-
return { ...noMatch$1 };
|
|
3312
|
-
}
|
|
3313
|
-
return {
|
|
3314
|
-
matched: true,
|
|
3315
|
-
consumedSegments: [],
|
|
3316
|
-
remainingSegments: segments,
|
|
3317
|
-
parameters: {},
|
|
3318
|
-
positionalParamSegments: {}
|
|
3319
|
-
};
|
|
3320
|
-
}
|
|
3321
|
-
const matcher = route.matcher || defaultUrlMatcher;
|
|
3322
|
-
const res = matcher(segments, segmentGroup, route);
|
|
3323
|
-
if (!res)
|
|
3324
|
-
return { ...noMatch$1 };
|
|
3325
|
-
const posParams = {};
|
|
3326
|
-
Object.entries(res.posParams ?? {}).forEach(([k, v]) => {
|
|
3327
|
-
posParams[k] = v.path;
|
|
3328
|
-
});
|
|
3329
|
-
const parameters = res.consumed.length > 0 ?
|
|
3330
|
-
{ ...posParams, ...res.consumed[res.consumed.length - 1].parameters } :
|
|
3331
|
-
posParams;
|
|
3332
|
-
return {
|
|
3333
|
-
matched: true,
|
|
3334
|
-
consumedSegments: res.consumed,
|
|
3335
|
-
remainingSegments: segments.slice(res.consumed.length),
|
|
3336
|
-
// TODO(atscott): investigate combining parameters and positionalParamSegments
|
|
3337
|
-
parameters,
|
|
3338
|
-
positionalParamSegments: res.posParams ?? {}
|
|
3339
|
-
};
|
|
3340
|
-
}
|
|
3341
|
-
function split(segmentGroup, consumedSegments, slicedSegments, config) {
|
|
3342
|
-
if (slicedSegments.length > 0 &&
|
|
3343
|
-
containsEmptyPathMatchesWithNamedOutlets(segmentGroup, slicedSegments, config)) {
|
|
3344
|
-
const s = new UrlSegmentGroup(consumedSegments, createChildrenForEmptyPaths(config, new UrlSegmentGroup(slicedSegments, segmentGroup.children)));
|
|
3345
|
-
return { segmentGroup: s, slicedSegments: [] };
|
|
3346
|
-
}
|
|
3347
|
-
if (slicedSegments.length === 0 &&
|
|
3348
|
-
containsEmptyPathMatches(segmentGroup, slicedSegments, config)) {
|
|
3349
|
-
const s = new UrlSegmentGroup(segmentGroup.segments, addEmptyPathsToChildrenIfNeeded(segmentGroup, consumedSegments, slicedSegments, config, segmentGroup.children));
|
|
3350
|
-
return { segmentGroup: s, slicedSegments };
|
|
3351
|
-
}
|
|
3352
|
-
const s = new UrlSegmentGroup(segmentGroup.segments, segmentGroup.children);
|
|
3353
|
-
return { segmentGroup: s, slicedSegments };
|
|
3354
|
-
}
|
|
3355
|
-
function addEmptyPathsToChildrenIfNeeded(segmentGroup, consumedSegments, slicedSegments, routes, children) {
|
|
3356
|
-
const res = {};
|
|
3357
|
-
for (const r of routes) {
|
|
3358
|
-
if (emptyPathMatch(segmentGroup, slicedSegments, r) && !children[getOutlet(r)]) {
|
|
3359
|
-
const s = new UrlSegmentGroup([], {});
|
|
3360
|
-
res[getOutlet(r)] = s;
|
|
3361
|
-
}
|
|
3362
|
-
}
|
|
3363
|
-
return { ...children, ...res };
|
|
3364
|
-
}
|
|
3365
|
-
function createChildrenForEmptyPaths(routes, primarySegment) {
|
|
3366
|
-
const res = {};
|
|
3367
|
-
res[PRIMARY_OUTLET] = primarySegment;
|
|
3368
|
-
for (const r of routes) {
|
|
3369
|
-
if (r.path === '' && getOutlet(r) !== PRIMARY_OUTLET) {
|
|
3370
|
-
const s = new UrlSegmentGroup([], {});
|
|
3371
|
-
res[getOutlet(r)] = s;
|
|
3372
|
-
}
|
|
3373
|
-
}
|
|
3374
|
-
return res;
|
|
3375
|
-
}
|
|
3376
|
-
function containsEmptyPathMatchesWithNamedOutlets(segmentGroup, slicedSegments, routes) {
|
|
3377
|
-
return routes.some(r => emptyPathMatch(segmentGroup, slicedSegments, r) && getOutlet(r) !== PRIMARY_OUTLET);
|
|
3378
|
-
}
|
|
3379
|
-
function containsEmptyPathMatches(segmentGroup, slicedSegments, routes) {
|
|
3380
|
-
return routes.some(r => emptyPathMatch(segmentGroup, slicedSegments, r));
|
|
3381
|
-
}
|
|
3382
|
-
function emptyPathMatch(segmentGroup, slicedSegments, r) {
|
|
3383
|
-
if ((segmentGroup.hasChildren() || slicedSegments.length > 0) && r.pathMatch === 'full') {
|
|
3384
|
-
return false;
|
|
3385
|
-
}
|
|
3386
|
-
return r.path === '';
|
|
3387
|
-
}
|
|
3388
|
-
/**
|
|
3389
|
-
* Determines if `route` is a path match for the `rawSegment`, `segments`, and `outlet` without
|
|
3390
|
-
* verifying that its children are a full match for the remainder of the `rawSegment` children as
|
|
3391
|
-
* well.
|
|
3392
|
-
*/
|
|
3393
|
-
function isImmediateMatch(route, rawSegment, segments, outlet) {
|
|
3394
|
-
// We allow matches to empty paths when the outlets differ so we can match a url like `/(b:b)` to
|
|
3395
|
-
// a config like
|
|
3396
|
-
// * `{path: '', children: [{path: 'b', outlet: 'b'}]}`
|
|
3397
|
-
// or even
|
|
3398
|
-
// * `{path: '', outlet: 'a', children: [{path: 'b', outlet: 'b'}]`
|
|
3399
|
-
//
|
|
3400
|
-
// The exception here is when the segment outlet is for the primary outlet. This would
|
|
3401
|
-
// result in a match inside the named outlet because all children there are written as primary
|
|
3402
|
-
// outlets. So we need to prevent child named outlet matches in a url like `/b` in a config like
|
|
3403
|
-
// * `{path: '', outlet: 'x' children: [{path: 'b'}]}`
|
|
3404
|
-
// This should only match if the url is `/(x:b)`.
|
|
3405
|
-
if (getOutlet(route) !== outlet &&
|
|
3406
|
-
(outlet === PRIMARY_OUTLET || !emptyPathMatch(rawSegment, segments, route))) {
|
|
3407
|
-
return false;
|
|
3408
|
-
}
|
|
3409
|
-
if (route.path === '**') {
|
|
3410
|
-
return true;
|
|
3411
|
-
}
|
|
3412
|
-
return match(rawSegment, route, segments).matched;
|
|
3413
|
-
}
|
|
3414
|
-
function noLeftoversInUrl(segmentGroup, segments, outlet) {
|
|
3415
|
-
return segments.length === 0 && !segmentGroup.children[outlet];
|
|
3416
|
-
}
|
|
3417
|
-
|
|
3418
|
-
const NG_DEV_MODE$7 = typeof ngDevMode === 'undefined' || ngDevMode;
|
|
3419
|
-
class NoMatch$1 {
|
|
3390
|
+
class NoMatch {
|
|
3420
3391
|
constructor(segmentGroup) {
|
|
3421
3392
|
this.segmentGroup = segmentGroup || null;
|
|
3422
3393
|
}
|
|
@@ -3426,241 +3397,28 @@ class AbsoluteRedirect {
|
|
|
3426
3397
|
this.urlTree = urlTree;
|
|
3427
3398
|
}
|
|
3428
3399
|
}
|
|
3429
|
-
function noMatch(segmentGroup) {
|
|
3430
|
-
return throwError(new NoMatch
|
|
3400
|
+
function noMatch$1(segmentGroup) {
|
|
3401
|
+
return throwError(new NoMatch(segmentGroup));
|
|
3431
3402
|
}
|
|
3432
3403
|
function absoluteRedirect(newTree) {
|
|
3433
3404
|
return throwError(new AbsoluteRedirect(newTree));
|
|
3434
3405
|
}
|
|
3435
3406
|
function namedOutletsRedirect(redirectTo) {
|
|
3436
|
-
return throwError(new ɵRuntimeError(4000 /* RuntimeErrorCode.NAMED_OUTLET_REDIRECT */,
|
|
3407
|
+
return throwError(new ɵRuntimeError(4000 /* RuntimeErrorCode.NAMED_OUTLET_REDIRECT */, (typeof ngDevMode === 'undefined' || ngDevMode) &&
|
|
3437
3408
|
`Only absolute redirects can have named outlets. redirectTo: '${redirectTo}'`));
|
|
3438
3409
|
}
|
|
3439
3410
|
function canLoadFails(route) {
|
|
3440
|
-
return throwError(navigationCancelingError(
|
|
3411
|
+
return throwError(navigationCancelingError((typeof ngDevMode === 'undefined' || ngDevMode) &&
|
|
3441
3412
|
`Cannot load children because the guard of the route "path: '${route.path}'" returned false`, 3 /* NavigationCancellationCode.GuardRejected */));
|
|
3442
3413
|
}
|
|
3443
|
-
/**
|
|
3444
|
-
* Returns the `UrlTree` with the redirection applied.
|
|
3445
|
-
*
|
|
3446
|
-
* Lazy modules are loaded along the way.
|
|
3447
|
-
*/
|
|
3448
|
-
function applyRedirects$1(injector, configLoader, urlSerializer, urlTree, config) {
|
|
3449
|
-
return new ApplyRedirects(injector, configLoader, urlSerializer, urlTree, config).apply();
|
|
3450
|
-
}
|
|
3451
3414
|
class ApplyRedirects {
|
|
3452
|
-
constructor(
|
|
3453
|
-
this.injector = injector;
|
|
3454
|
-
this.configLoader = configLoader;
|
|
3415
|
+
constructor(urlSerializer, urlTree) {
|
|
3455
3416
|
this.urlSerializer = urlSerializer;
|
|
3456
3417
|
this.urlTree = urlTree;
|
|
3457
|
-
this.config = config;
|
|
3458
|
-
this.allowRedirects = true;
|
|
3459
|
-
}
|
|
3460
|
-
apply() {
|
|
3461
|
-
const splitGroup = split(this.urlTree.root, [], [], this.config).segmentGroup;
|
|
3462
|
-
// TODO(atscott): creating a new segment removes the _sourceSegment _segmentIndexShift, which is
|
|
3463
|
-
// only necessary to prevent failures in tests which assert exact object matches. The `split` is
|
|
3464
|
-
// now shared between `applyRedirects` and `recognize` but only the `recognize` step needs these
|
|
3465
|
-
// properties. Before the implementations were merged, the `applyRedirects` would not assign
|
|
3466
|
-
// them. We should be able to remove this logic as a "breaking change" but should do some more
|
|
3467
|
-
// investigation into the failures first.
|
|
3468
|
-
const rootSegmentGroup = new UrlSegmentGroup(splitGroup.segments, splitGroup.children);
|
|
3469
|
-
const expanded$ = this.expandSegmentGroup(this.injector, this.config, rootSegmentGroup, PRIMARY_OUTLET);
|
|
3470
|
-
const urlTrees$ = expanded$.pipe(map((rootSegmentGroup) => {
|
|
3471
|
-
return this.createUrlTree(squashSegmentGroup(rootSegmentGroup), this.urlTree.queryParams, this.urlTree.fragment);
|
|
3472
|
-
}));
|
|
3473
|
-
return urlTrees$.pipe(catchError((e) => {
|
|
3474
|
-
if (e instanceof AbsoluteRedirect) {
|
|
3475
|
-
// After an absolute redirect we do not apply any more redirects!
|
|
3476
|
-
// If this implementation changes, update the documentation note in `redirectTo`.
|
|
3477
|
-
this.allowRedirects = false;
|
|
3478
|
-
// we need to run matching, so we can fetch all lazy-loaded modules
|
|
3479
|
-
return this.match(e.urlTree);
|
|
3480
|
-
}
|
|
3481
|
-
if (e instanceof NoMatch$1) {
|
|
3482
|
-
throw this.noMatchError(e);
|
|
3483
|
-
}
|
|
3484
|
-
throw e;
|
|
3485
|
-
}));
|
|
3486
|
-
}
|
|
3487
|
-
match(tree) {
|
|
3488
|
-
const expanded$ = this.expandSegmentGroup(this.injector, this.config, tree.root, PRIMARY_OUTLET);
|
|
3489
|
-
const mapped$ = expanded$.pipe(map((rootSegmentGroup) => {
|
|
3490
|
-
return this.createUrlTree(squashSegmentGroup(rootSegmentGroup), tree.queryParams, tree.fragment);
|
|
3491
|
-
}));
|
|
3492
|
-
return mapped$.pipe(catchError((e) => {
|
|
3493
|
-
if (e instanceof NoMatch$1) {
|
|
3494
|
-
throw this.noMatchError(e);
|
|
3495
|
-
}
|
|
3496
|
-
throw e;
|
|
3497
|
-
}));
|
|
3498
3418
|
}
|
|
3499
3419
|
noMatchError(e) {
|
|
3500
|
-
return new ɵRuntimeError(4002 /* RuntimeErrorCode.NO_MATCH */,
|
|
3501
|
-
|
|
3502
|
-
createUrlTree(rootCandidate, queryParams, fragment) {
|
|
3503
|
-
const root = createRoot(rootCandidate);
|
|
3504
|
-
return new UrlTree(root, queryParams, fragment);
|
|
3505
|
-
}
|
|
3506
|
-
expandSegmentGroup(injector, routes, segmentGroup, outlet) {
|
|
3507
|
-
if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) {
|
|
3508
|
-
return this.expandChildren(injector, routes, segmentGroup)
|
|
3509
|
-
.pipe(map((children) => new UrlSegmentGroup([], children)));
|
|
3510
|
-
}
|
|
3511
|
-
return this.expandSegment(injector, segmentGroup, routes, segmentGroup.segments, outlet, true);
|
|
3512
|
-
}
|
|
3513
|
-
// Recursively expand segment groups for all the child outlets
|
|
3514
|
-
expandChildren(injector, routes, segmentGroup) {
|
|
3515
|
-
// Expand outlets one at a time, starting with the primary outlet. We need to do it this way
|
|
3516
|
-
// because an absolute redirect from the primary outlet takes precedence.
|
|
3517
|
-
const childOutlets = [];
|
|
3518
|
-
for (const child of Object.keys(segmentGroup.children)) {
|
|
3519
|
-
if (child === 'primary') {
|
|
3520
|
-
childOutlets.unshift(child);
|
|
3521
|
-
}
|
|
3522
|
-
else {
|
|
3523
|
-
childOutlets.push(child);
|
|
3524
|
-
}
|
|
3525
|
-
}
|
|
3526
|
-
return from(childOutlets)
|
|
3527
|
-
.pipe(concatMap(childOutlet => {
|
|
3528
|
-
const child = segmentGroup.children[childOutlet];
|
|
3529
|
-
// Sort the routes so routes with outlets that match the segment appear
|
|
3530
|
-
// first, followed by routes for other outlets, which might match if they have an
|
|
3531
|
-
// empty path.
|
|
3532
|
-
const sortedRoutes = sortByMatchingOutlets(routes, childOutlet);
|
|
3533
|
-
return this.expandSegmentGroup(injector, sortedRoutes, child, childOutlet)
|
|
3534
|
-
.pipe(map(s => ({ segment: s, outlet: childOutlet })));
|
|
3535
|
-
}), scan((children, expandedChild) => {
|
|
3536
|
-
children[expandedChild.outlet] = expandedChild.segment;
|
|
3537
|
-
return children;
|
|
3538
|
-
}, {}), last$1());
|
|
3539
|
-
}
|
|
3540
|
-
expandSegment(injector, segmentGroup, routes, segments, outlet, allowRedirects) {
|
|
3541
|
-
return from(routes).pipe(concatMap(r => {
|
|
3542
|
-
const expanded$ = this.expandSegmentAgainstRoute(injector, segmentGroup, routes, r, segments, outlet, allowRedirects);
|
|
3543
|
-
return expanded$.pipe(catchError((e) => {
|
|
3544
|
-
if (e instanceof NoMatch$1) {
|
|
3545
|
-
return of(null);
|
|
3546
|
-
}
|
|
3547
|
-
throw e;
|
|
3548
|
-
}));
|
|
3549
|
-
}), first((s) => !!s), catchError((e, _) => {
|
|
3550
|
-
if (isEmptyError(e)) {
|
|
3551
|
-
if (noLeftoversInUrl(segmentGroup, segments, outlet)) {
|
|
3552
|
-
return of(new UrlSegmentGroup([], {}));
|
|
3553
|
-
}
|
|
3554
|
-
return noMatch(segmentGroup);
|
|
3555
|
-
}
|
|
3556
|
-
throw e;
|
|
3557
|
-
}));
|
|
3558
|
-
}
|
|
3559
|
-
expandSegmentAgainstRoute(injector, segmentGroup, routes, route, paths, outlet, allowRedirects) {
|
|
3560
|
-
if (!isImmediateMatch(route, segmentGroup, paths, outlet)) {
|
|
3561
|
-
return noMatch(segmentGroup);
|
|
3562
|
-
}
|
|
3563
|
-
if (route.redirectTo === undefined) {
|
|
3564
|
-
return this.matchSegmentAgainstRoute(injector, segmentGroup, route, paths, outlet);
|
|
3565
|
-
}
|
|
3566
|
-
if (allowRedirects && this.allowRedirects) {
|
|
3567
|
-
return this.expandSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, paths, outlet);
|
|
3568
|
-
}
|
|
3569
|
-
return noMatch(segmentGroup);
|
|
3570
|
-
}
|
|
3571
|
-
expandSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet) {
|
|
3572
|
-
if (route.path === '**') {
|
|
3573
|
-
return this.expandWildCardWithParamsAgainstRouteUsingRedirect(injector, routes, route, outlet);
|
|
3574
|
-
}
|
|
3575
|
-
return this.expandRegularSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet);
|
|
3576
|
-
}
|
|
3577
|
-
expandWildCardWithParamsAgainstRouteUsingRedirect(injector, routes, route, outlet) {
|
|
3578
|
-
const newTree = this.applyRedirectCommands([], route.redirectTo, {});
|
|
3579
|
-
if (route.redirectTo.startsWith('/')) {
|
|
3580
|
-
return absoluteRedirect(newTree);
|
|
3581
|
-
}
|
|
3582
|
-
return this.lineralizeSegments(route, newTree).pipe(mergeMap((newSegments) => {
|
|
3583
|
-
const group = new UrlSegmentGroup(newSegments, {});
|
|
3584
|
-
return this.expandSegment(injector, group, routes, newSegments, outlet, false);
|
|
3585
|
-
}));
|
|
3586
|
-
}
|
|
3587
|
-
expandRegularSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet) {
|
|
3588
|
-
const { matched, consumedSegments, remainingSegments, positionalParamSegments } = match(segmentGroup, route, segments);
|
|
3589
|
-
if (!matched)
|
|
3590
|
-
return noMatch(segmentGroup);
|
|
3591
|
-
const newTree = this.applyRedirectCommands(consumedSegments, route.redirectTo, positionalParamSegments);
|
|
3592
|
-
if (route.redirectTo.startsWith('/')) {
|
|
3593
|
-
return absoluteRedirect(newTree);
|
|
3594
|
-
}
|
|
3595
|
-
return this.lineralizeSegments(route, newTree).pipe(mergeMap((newSegments) => {
|
|
3596
|
-
return this.expandSegment(injector, segmentGroup, routes, newSegments.concat(remainingSegments), outlet, false);
|
|
3597
|
-
}));
|
|
3598
|
-
}
|
|
3599
|
-
matchSegmentAgainstRoute(injector, rawSegmentGroup, route, segments, outlet) {
|
|
3600
|
-
if (route.path === '**') {
|
|
3601
|
-
// Only create the Route's `EnvironmentInjector` if it matches the attempted navigation
|
|
3602
|
-
injector = getOrCreateRouteInjectorIfNeeded(route, injector);
|
|
3603
|
-
if (route.loadChildren) {
|
|
3604
|
-
const loaded$ = route._loadedRoutes ?
|
|
3605
|
-
of({ routes: route._loadedRoutes, injector: route._loadedInjector }) :
|
|
3606
|
-
this.configLoader.loadChildren(injector, route);
|
|
3607
|
-
return loaded$.pipe(map((cfg) => {
|
|
3608
|
-
route._loadedRoutes = cfg.routes;
|
|
3609
|
-
route._loadedInjector = cfg.injector;
|
|
3610
|
-
return new UrlSegmentGroup(segments, {});
|
|
3611
|
-
}));
|
|
3612
|
-
}
|
|
3613
|
-
return of(new UrlSegmentGroup(segments, {}));
|
|
3614
|
-
}
|
|
3615
|
-
return matchWithChecks(rawSegmentGroup, route, segments, injector, this.urlSerializer)
|
|
3616
|
-
.pipe(switchMap(({ matched, consumedSegments, remainingSegments }) => {
|
|
3617
|
-
if (!matched)
|
|
3618
|
-
return noMatch(rawSegmentGroup);
|
|
3619
|
-
// If the route has an injector created from providers, we should start using that.
|
|
3620
|
-
injector = route._injector ?? injector;
|
|
3621
|
-
const childConfig$ = this.getChildConfig(injector, route, segments);
|
|
3622
|
-
return childConfig$.pipe(mergeMap((routerConfig) => {
|
|
3623
|
-
const childInjector = routerConfig.injector ?? injector;
|
|
3624
|
-
const childConfig = routerConfig.routes;
|
|
3625
|
-
const { segmentGroup: splitSegmentGroup, slicedSegments } = split(rawSegmentGroup, consumedSegments, remainingSegments, childConfig);
|
|
3626
|
-
// See comment on the other call to `split` about why this is necessary.
|
|
3627
|
-
const segmentGroup = new UrlSegmentGroup(splitSegmentGroup.segments, splitSegmentGroup.children);
|
|
3628
|
-
if (slicedSegments.length === 0 && segmentGroup.hasChildren()) {
|
|
3629
|
-
const expanded$ = this.expandChildren(childInjector, childConfig, segmentGroup);
|
|
3630
|
-
return expanded$.pipe(map((children) => new UrlSegmentGroup(consumedSegments, children)));
|
|
3631
|
-
}
|
|
3632
|
-
if (childConfig.length === 0 && slicedSegments.length === 0) {
|
|
3633
|
-
return of(new UrlSegmentGroup(consumedSegments, {}));
|
|
3634
|
-
}
|
|
3635
|
-
const matchedOnOutlet = getOutlet(route) === outlet;
|
|
3636
|
-
const expanded$ = this.expandSegment(childInjector, segmentGroup, childConfig, slicedSegments, matchedOnOutlet ? PRIMARY_OUTLET : outlet, true);
|
|
3637
|
-
return expanded$.pipe(map((cs) => new UrlSegmentGroup(consumedSegments.concat(cs.segments), cs.children)));
|
|
3638
|
-
}));
|
|
3639
|
-
}));
|
|
3640
|
-
}
|
|
3641
|
-
getChildConfig(injector, route, segments) {
|
|
3642
|
-
if (route.children) {
|
|
3643
|
-
// The children belong to the same module
|
|
3644
|
-
return of({ routes: route.children, injector });
|
|
3645
|
-
}
|
|
3646
|
-
if (route.loadChildren) {
|
|
3647
|
-
// lazy children belong to the loaded module
|
|
3648
|
-
if (route._loadedRoutes !== undefined) {
|
|
3649
|
-
return of({ routes: route._loadedRoutes, injector: route._loadedInjector });
|
|
3650
|
-
}
|
|
3651
|
-
return runCanLoadGuards(injector, route, segments, this.urlSerializer)
|
|
3652
|
-
.pipe(mergeMap((shouldLoadResult) => {
|
|
3653
|
-
if (shouldLoadResult) {
|
|
3654
|
-
return this.configLoader.loadChildren(injector, route)
|
|
3655
|
-
.pipe(tap((cfg) => {
|
|
3656
|
-
route._loadedRoutes = cfg.routes;
|
|
3657
|
-
route._loadedInjector = cfg.injector;
|
|
3658
|
-
}));
|
|
3659
|
-
}
|
|
3660
|
-
return canLoadFails(route);
|
|
3661
|
-
}));
|
|
3662
|
-
}
|
|
3663
|
-
return of({ routes: [], injector });
|
|
3420
|
+
return new ɵRuntimeError(4002 /* RuntimeErrorCode.NO_MATCH */, (typeof ngDevMode === 'undefined' || ngDevMode) &&
|
|
3421
|
+
`Cannot match any routes. URL Segment: '${e.segmentGroup}'`);
|
|
3664
3422
|
}
|
|
3665
3423
|
lineralizeSegments(route, urlTree) {
|
|
3666
3424
|
let res = [];
|
|
@@ -3712,7 +3470,7 @@ class ApplyRedirects {
|
|
|
3712
3470
|
findPosParam(redirectTo, redirectToUrlSegment, posParams) {
|
|
3713
3471
|
const pos = posParams[redirectToUrlSegment.path.substring(1)];
|
|
3714
3472
|
if (!pos)
|
|
3715
|
-
throw new ɵRuntimeError(4001 /* RuntimeErrorCode.MISSING_REDIRECT */,
|
|
3473
|
+
throw new ɵRuntimeError(4001 /* RuntimeErrorCode.MISSING_REDIRECT */, (typeof ngDevMode === 'undefined' || ngDevMode) &&
|
|
3716
3474
|
`Cannot redirect to '${redirectTo}'. Cannot find '${redirectToUrlSegment.path}'.`);
|
|
3717
3475
|
return pos;
|
|
3718
3476
|
}
|
|
@@ -3725,59 +3483,196 @@ class ApplyRedirects {
|
|
|
3725
3483
|
}
|
|
3726
3484
|
idx++;
|
|
3727
3485
|
}
|
|
3728
|
-
return redirectToUrlSegment;
|
|
3486
|
+
return redirectToUrlSegment;
|
|
3487
|
+
}
|
|
3488
|
+
}
|
|
3489
|
+
|
|
3490
|
+
const noMatch = {
|
|
3491
|
+
matched: false,
|
|
3492
|
+
consumedSegments: [],
|
|
3493
|
+
remainingSegments: [],
|
|
3494
|
+
parameters: {},
|
|
3495
|
+
positionalParamSegments: {}
|
|
3496
|
+
};
|
|
3497
|
+
function matchWithChecks(segmentGroup, route, segments, injector, urlSerializer) {
|
|
3498
|
+
const result = match(segmentGroup, route, segments);
|
|
3499
|
+
if (!result.matched) {
|
|
3500
|
+
return of(result);
|
|
3501
|
+
}
|
|
3502
|
+
// Only create the Route's `EnvironmentInjector` if it matches the attempted
|
|
3503
|
+
// navigation
|
|
3504
|
+
injector = getOrCreateRouteInjectorIfNeeded(route, injector);
|
|
3505
|
+
return runCanMatchGuards(injector, route, segments, urlSerializer)
|
|
3506
|
+
.pipe(map((v) => v === true ? result : { ...noMatch }));
|
|
3507
|
+
}
|
|
3508
|
+
function match(segmentGroup, route, segments) {
|
|
3509
|
+
if (route.path === '') {
|
|
3510
|
+
if (route.pathMatch === 'full' && (segmentGroup.hasChildren() || segments.length > 0)) {
|
|
3511
|
+
return { ...noMatch };
|
|
3512
|
+
}
|
|
3513
|
+
return {
|
|
3514
|
+
matched: true,
|
|
3515
|
+
consumedSegments: [],
|
|
3516
|
+
remainingSegments: segments,
|
|
3517
|
+
parameters: {},
|
|
3518
|
+
positionalParamSegments: {}
|
|
3519
|
+
};
|
|
3520
|
+
}
|
|
3521
|
+
const matcher = route.matcher || defaultUrlMatcher;
|
|
3522
|
+
const res = matcher(segments, segmentGroup, route);
|
|
3523
|
+
if (!res)
|
|
3524
|
+
return { ...noMatch };
|
|
3525
|
+
const posParams = {};
|
|
3526
|
+
Object.entries(res.posParams ?? {}).forEach(([k, v]) => {
|
|
3527
|
+
posParams[k] = v.path;
|
|
3528
|
+
});
|
|
3529
|
+
const parameters = res.consumed.length > 0 ?
|
|
3530
|
+
{ ...posParams, ...res.consumed[res.consumed.length - 1].parameters } :
|
|
3531
|
+
posParams;
|
|
3532
|
+
return {
|
|
3533
|
+
matched: true,
|
|
3534
|
+
consumedSegments: res.consumed,
|
|
3535
|
+
remainingSegments: segments.slice(res.consumed.length),
|
|
3536
|
+
// TODO(atscott): investigate combining parameters and positionalParamSegments
|
|
3537
|
+
parameters,
|
|
3538
|
+
positionalParamSegments: res.posParams ?? {}
|
|
3539
|
+
};
|
|
3540
|
+
}
|
|
3541
|
+
function split(segmentGroup, consumedSegments, slicedSegments, config) {
|
|
3542
|
+
if (slicedSegments.length > 0 &&
|
|
3543
|
+
containsEmptyPathMatchesWithNamedOutlets(segmentGroup, slicedSegments, config)) {
|
|
3544
|
+
const s = new UrlSegmentGroup(consumedSegments, createChildrenForEmptyPaths(config, new UrlSegmentGroup(slicedSegments, segmentGroup.children)));
|
|
3545
|
+
return { segmentGroup: s, slicedSegments: [] };
|
|
3546
|
+
}
|
|
3547
|
+
if (slicedSegments.length === 0 &&
|
|
3548
|
+
containsEmptyPathMatches(segmentGroup, slicedSegments, config)) {
|
|
3549
|
+
const s = new UrlSegmentGroup(segmentGroup.segments, addEmptyPathsToChildrenIfNeeded(segmentGroup, consumedSegments, slicedSegments, config, segmentGroup.children));
|
|
3550
|
+
return { segmentGroup: s, slicedSegments };
|
|
3551
|
+
}
|
|
3552
|
+
const s = new UrlSegmentGroup(segmentGroup.segments, segmentGroup.children);
|
|
3553
|
+
return { segmentGroup: s, slicedSegments };
|
|
3554
|
+
}
|
|
3555
|
+
function addEmptyPathsToChildrenIfNeeded(segmentGroup, consumedSegments, slicedSegments, routes, children) {
|
|
3556
|
+
const res = {};
|
|
3557
|
+
for (const r of routes) {
|
|
3558
|
+
if (emptyPathMatch(segmentGroup, slicedSegments, r) && !children[getOutlet(r)]) {
|
|
3559
|
+
const s = new UrlSegmentGroup([], {});
|
|
3560
|
+
res[getOutlet(r)] = s;
|
|
3561
|
+
}
|
|
3562
|
+
}
|
|
3563
|
+
return { ...children, ...res };
|
|
3564
|
+
}
|
|
3565
|
+
function createChildrenForEmptyPaths(routes, primarySegment) {
|
|
3566
|
+
const res = {};
|
|
3567
|
+
res[PRIMARY_OUTLET] = primarySegment;
|
|
3568
|
+
for (const r of routes) {
|
|
3569
|
+
if (r.path === '' && getOutlet(r) !== PRIMARY_OUTLET) {
|
|
3570
|
+
const s = new UrlSegmentGroup([], {});
|
|
3571
|
+
res[getOutlet(r)] = s;
|
|
3572
|
+
}
|
|
3729
3573
|
}
|
|
3574
|
+
return res;
|
|
3730
3575
|
}
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
return switchMap(t => applyRedirects$1(environmentInjector, configLoader, urlSerializer, t.extractedUrl, config)
|
|
3734
|
-
.pipe(map(urlAfterRedirects => ({ ...t, urlAfterRedirects }))));
|
|
3576
|
+
function containsEmptyPathMatchesWithNamedOutlets(segmentGroup, slicedSegments, routes) {
|
|
3577
|
+
return routes.some(r => emptyPathMatch(segmentGroup, slicedSegments, r) && getOutlet(r) !== PRIMARY_OUTLET);
|
|
3735
3578
|
}
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
class NoMatch {
|
|
3579
|
+
function containsEmptyPathMatches(segmentGroup, slicedSegments, routes) {
|
|
3580
|
+
return routes.some(r => emptyPathMatch(segmentGroup, slicedSegments, r));
|
|
3739
3581
|
}
|
|
3740
|
-
function
|
|
3741
|
-
|
|
3742
|
-
|
|
3582
|
+
function emptyPathMatch(segmentGroup, slicedSegments, r) {
|
|
3583
|
+
if ((segmentGroup.hasChildren() || slicedSegments.length > 0) && r.pathMatch === 'full') {
|
|
3584
|
+
return false;
|
|
3585
|
+
}
|
|
3586
|
+
return r.path === '';
|
|
3743
3587
|
}
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
}
|
|
3588
|
+
/**
|
|
3589
|
+
* Determines if `route` is a path match for the `rawSegment`, `segments`, and `outlet` without
|
|
3590
|
+
* verifying that its children are a full match for the remainder of the `rawSegment` children as
|
|
3591
|
+
* well.
|
|
3592
|
+
*/
|
|
3593
|
+
function isImmediateMatch(route, rawSegment, segments, outlet) {
|
|
3594
|
+
// We allow matches to empty paths when the outlets differ so we can match a url like `/(b:b)` to
|
|
3595
|
+
// a config like
|
|
3596
|
+
// * `{path: '', children: [{path: 'b', outlet: 'b'}]}`
|
|
3597
|
+
// or even
|
|
3598
|
+
// * `{path: '', outlet: 'a', children: [{path: 'b', outlet: 'b'}]`
|
|
3599
|
+
//
|
|
3600
|
+
// The exception here is when the segment outlet is for the primary outlet. This would
|
|
3601
|
+
// result in a match inside the named outlet because all children there are written as primary
|
|
3602
|
+
// outlets. So we need to prevent child named outlet matches in a url like `/b` in a config like
|
|
3603
|
+
// * `{path: '', outlet: 'x' children: [{path: 'b'}]}`
|
|
3604
|
+
// This should only match if the url is `/(x:b)`.
|
|
3605
|
+
if (getOutlet(route) !== outlet &&
|
|
3606
|
+
(outlet === PRIMARY_OUTLET || !emptyPathMatch(rawSegment, segments, route))) {
|
|
3607
|
+
return false;
|
|
3608
|
+
}
|
|
3609
|
+
if (route.path === '**') {
|
|
3610
|
+
return true;
|
|
3611
|
+
}
|
|
3612
|
+
return match(rawSegment, route, segments).matched;
|
|
3613
|
+
}
|
|
3614
|
+
function noLeftoversInUrl(segmentGroup, segments, outlet) {
|
|
3615
|
+
return segments.length === 0 && !segmentGroup.children[outlet];
|
|
3616
|
+
}
|
|
3617
|
+
|
|
3618
|
+
function recognize$1(injector, configLoader, rootComponentType, config, urlTree, urlSerializer, paramsInheritanceStrategy = 'emptyOnly') {
|
|
3619
|
+
return new Recognizer(injector, configLoader, rootComponentType, config, urlTree, paramsInheritanceStrategy, urlSerializer)
|
|
3620
|
+
.recognize();
|
|
3755
3621
|
}
|
|
3756
3622
|
class Recognizer {
|
|
3757
|
-
constructor(injector, rootComponentType, config, urlTree,
|
|
3623
|
+
constructor(injector, configLoader, rootComponentType, config, urlTree, paramsInheritanceStrategy, urlSerializer) {
|
|
3758
3624
|
this.injector = injector;
|
|
3625
|
+
this.configLoader = configLoader;
|
|
3759
3626
|
this.rootComponentType = rootComponentType;
|
|
3760
3627
|
this.config = config;
|
|
3761
3628
|
this.urlTree = urlTree;
|
|
3762
|
-
this.url = url;
|
|
3763
3629
|
this.paramsInheritanceStrategy = paramsInheritanceStrategy;
|
|
3764
3630
|
this.urlSerializer = urlSerializer;
|
|
3631
|
+
this.allowRedirects = true;
|
|
3632
|
+
this.applyRedirects = new ApplyRedirects(this.urlSerializer, this.urlTree);
|
|
3633
|
+
}
|
|
3634
|
+
noMatchError(e) {
|
|
3635
|
+
return new ɵRuntimeError(4002 /* RuntimeErrorCode.NO_MATCH */, (typeof ngDevMode === 'undefined' || ngDevMode) &&
|
|
3636
|
+
`Cannot match any routes. URL Segment: '${e.segmentGroup}'`);
|
|
3765
3637
|
}
|
|
3766
3638
|
recognize() {
|
|
3767
|
-
const rootSegmentGroup = split(this.urlTree.root, [], [], this.config.
|
|
3768
|
-
.segmentGroup;
|
|
3639
|
+
const rootSegmentGroup = split(this.urlTree.root, [], [], this.config).segmentGroup;
|
|
3769
3640
|
return this.processSegmentGroup(this.injector, this.config, rootSegmentGroup, PRIMARY_OUTLET)
|
|
3770
|
-
.pipe(
|
|
3771
|
-
if (
|
|
3772
|
-
|
|
3641
|
+
.pipe(catchError((e) => {
|
|
3642
|
+
if (e instanceof AbsoluteRedirect) {
|
|
3643
|
+
// After an absolute redirect we do not apply any more redirects!
|
|
3644
|
+
// If this implementation changes, update the documentation note in `redirectTo`.
|
|
3645
|
+
this.allowRedirects = false;
|
|
3646
|
+
this.urlTree = e.urlTree;
|
|
3647
|
+
return this.match(e.urlTree);
|
|
3648
|
+
}
|
|
3649
|
+
if (e instanceof NoMatch) {
|
|
3650
|
+
throw this.noMatchError(e);
|
|
3773
3651
|
}
|
|
3774
|
-
|
|
3775
|
-
|
|
3652
|
+
throw e;
|
|
3653
|
+
}), map(children => {
|
|
3654
|
+
// Use Object.freeze to prevent readers of the Router state from modifying it outside
|
|
3655
|
+
// of a navigation, resulting in the router being out of sync with the browser.
|
|
3776
3656
|
const root = new ActivatedRouteSnapshot([], Object.freeze({}), Object.freeze({ ...this.urlTree.queryParams }), this.urlTree.fragment, {}, PRIMARY_OUTLET, this.rootComponentType, null, {});
|
|
3777
3657
|
const rootNode = new TreeNode(root, children);
|
|
3778
|
-
const routeState = new RouterStateSnapshot(
|
|
3658
|
+
const routeState = new RouterStateSnapshot('', rootNode);
|
|
3659
|
+
const tree = createUrlTreeFromSnapshot(root, [], this.urlTree.queryParams, this.urlTree.fragment);
|
|
3660
|
+
// https://github.com/angular/angular/issues/47307
|
|
3661
|
+
// Creating the tree stringifies the query params
|
|
3662
|
+
// We don't want to do this here so reassign them to the original.
|
|
3663
|
+
tree.queryParams = this.urlTree.queryParams;
|
|
3664
|
+
routeState.url = this.urlSerializer.serialize(tree);
|
|
3779
3665
|
this.inheritParamsAndData(routeState._root);
|
|
3780
|
-
return routeState;
|
|
3666
|
+
return { state: routeState, tree };
|
|
3667
|
+
}));
|
|
3668
|
+
}
|
|
3669
|
+
match(tree) {
|
|
3670
|
+
const expanded$ = this.processSegmentGroup(this.injector, this.config, tree.root, PRIMARY_OUTLET);
|
|
3671
|
+
return expanded$.pipe(catchError((e) => {
|
|
3672
|
+
if (e instanceof NoMatch) {
|
|
3673
|
+
throw this.noMatchError(e);
|
|
3674
|
+
}
|
|
3675
|
+
throw e;
|
|
3781
3676
|
}));
|
|
3782
3677
|
}
|
|
3783
3678
|
inheritParamsAndData(routeNode) {
|
|
@@ -3791,7 +3686,7 @@ class Recognizer {
|
|
|
3791
3686
|
if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) {
|
|
3792
3687
|
return this.processChildren(injector, config, segmentGroup);
|
|
3793
3688
|
}
|
|
3794
|
-
return this.processSegment(injector, config, segmentGroup, segmentGroup.segments, outlet);
|
|
3689
|
+
return this.processSegment(injector, config, segmentGroup, segmentGroup.segments, outlet, true);
|
|
3795
3690
|
}
|
|
3796
3691
|
/**
|
|
3797
3692
|
* Matches every child outlet in the `segmentGroup` to a `Route` in the config. Returns `null` if
|
|
@@ -3802,7 +3697,18 @@ class Recognizer {
|
|
|
3802
3697
|
* config.
|
|
3803
3698
|
*/
|
|
3804
3699
|
processChildren(injector, config, segmentGroup) {
|
|
3805
|
-
|
|
3700
|
+
// Expand outlets one at a time, starting with the primary outlet. We need to do it this way
|
|
3701
|
+
// because an absolute redirect from the primary outlet takes precedence.
|
|
3702
|
+
const childOutlets = [];
|
|
3703
|
+
for (const child of Object.keys(segmentGroup.children)) {
|
|
3704
|
+
if (child === 'primary') {
|
|
3705
|
+
childOutlets.unshift(child);
|
|
3706
|
+
}
|
|
3707
|
+
else {
|
|
3708
|
+
childOutlets.push(child);
|
|
3709
|
+
}
|
|
3710
|
+
}
|
|
3711
|
+
return from(childOutlets)
|
|
3806
3712
|
.pipe(concatMap(childOutlet => {
|
|
3807
3713
|
const child = segmentGroup.children[childOutlet];
|
|
3808
3714
|
// Sort the config so that routes with outlets that match the one being activated
|
|
@@ -3811,42 +3717,86 @@ class Recognizer {
|
|
|
3811
3717
|
const sortedConfig = sortByMatchingOutlets(config, childOutlet);
|
|
3812
3718
|
return this.processSegmentGroup(injector, sortedConfig, child, childOutlet);
|
|
3813
3719
|
}), scan((children, outletChildren) => {
|
|
3814
|
-
if (!children || !outletChildren)
|
|
3815
|
-
return null;
|
|
3816
3720
|
children.push(...outletChildren);
|
|
3817
3721
|
return children;
|
|
3818
|
-
}),
|
|
3722
|
+
}), defaultIfEmpty(null), last$1(), mergeMap(children => {
|
|
3819
3723
|
if (children === null)
|
|
3820
|
-
return
|
|
3724
|
+
return noMatch$1(segmentGroup);
|
|
3821
3725
|
// Because we may have matched two outlets to the same empty path segment, we can have
|
|
3822
3726
|
// multiple activated results for the same outlet. We should merge the children of
|
|
3823
3727
|
// these results so the final return value is only one `TreeNode` per outlet.
|
|
3824
3728
|
const mergedChildren = mergeEmptyPathMatches(children);
|
|
3825
|
-
if (
|
|
3729
|
+
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
3826
3730
|
// This should really never happen - we are only taking the first match for each
|
|
3827
3731
|
// outlet and merge the empty path matches.
|
|
3828
3732
|
checkOutletNameUniqueness(mergedChildren);
|
|
3829
3733
|
}
|
|
3830
3734
|
sortActivatedRouteSnapshots(mergedChildren);
|
|
3831
|
-
return mergedChildren;
|
|
3735
|
+
return of(mergedChildren);
|
|
3832
3736
|
}));
|
|
3833
3737
|
}
|
|
3834
|
-
processSegment(injector, routes, segmentGroup, segments, outlet) {
|
|
3738
|
+
processSegment(injector, routes, segmentGroup, segments, outlet, allowRedirects) {
|
|
3835
3739
|
return from(routes).pipe(concatMap(r => {
|
|
3836
|
-
return this
|
|
3740
|
+
return this
|
|
3741
|
+
.processSegmentAgainstRoute(r._injector ?? injector, routes, r, segmentGroup, segments, outlet, allowRedirects)
|
|
3742
|
+
.pipe(catchError((e) => {
|
|
3743
|
+
if (e instanceof NoMatch) {
|
|
3744
|
+
return of(null);
|
|
3745
|
+
}
|
|
3746
|
+
throw e;
|
|
3747
|
+
}));
|
|
3837
3748
|
}), first((x) => !!x), catchError(e => {
|
|
3838
3749
|
if (isEmptyError(e)) {
|
|
3839
3750
|
if (noLeftoversInUrl(segmentGroup, segments, outlet)) {
|
|
3840
3751
|
return of([]);
|
|
3841
3752
|
}
|
|
3842
|
-
return
|
|
3753
|
+
return noMatch$1(segmentGroup);
|
|
3843
3754
|
}
|
|
3844
3755
|
throw e;
|
|
3845
3756
|
}));
|
|
3846
3757
|
}
|
|
3847
|
-
processSegmentAgainstRoute(injector, route, rawSegment, segments, outlet) {
|
|
3848
|
-
if (
|
|
3849
|
-
return
|
|
3758
|
+
processSegmentAgainstRoute(injector, routes, route, rawSegment, segments, outlet, allowRedirects) {
|
|
3759
|
+
if (!isImmediateMatch(route, rawSegment, segments, outlet))
|
|
3760
|
+
return noMatch$1(rawSegment);
|
|
3761
|
+
if (route.redirectTo === undefined) {
|
|
3762
|
+
return this.matchSegmentAgainstRoute(injector, rawSegment, route, segments, outlet, allowRedirects);
|
|
3763
|
+
}
|
|
3764
|
+
if (allowRedirects && this.allowRedirects) {
|
|
3765
|
+
return this.expandSegmentAgainstRouteUsingRedirect(injector, rawSegment, routes, route, segments, outlet);
|
|
3766
|
+
}
|
|
3767
|
+
return noMatch$1(rawSegment);
|
|
3768
|
+
}
|
|
3769
|
+
expandSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet) {
|
|
3770
|
+
if (route.path === '**') {
|
|
3771
|
+
return this.expandWildCardWithParamsAgainstRouteUsingRedirect(injector, routes, route, outlet);
|
|
3772
|
+
}
|
|
3773
|
+
return this.expandRegularSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet);
|
|
3774
|
+
}
|
|
3775
|
+
expandWildCardWithParamsAgainstRouteUsingRedirect(injector, routes, route, outlet) {
|
|
3776
|
+
const newTree = this.applyRedirects.applyRedirectCommands([], route.redirectTo, {});
|
|
3777
|
+
if (route.redirectTo.startsWith('/')) {
|
|
3778
|
+
return absoluteRedirect(newTree);
|
|
3779
|
+
}
|
|
3780
|
+
return this.applyRedirects.lineralizeSegments(route, newTree)
|
|
3781
|
+
.pipe(mergeMap((newSegments) => {
|
|
3782
|
+
const group = new UrlSegmentGroup(newSegments, {});
|
|
3783
|
+
return this.processSegment(injector, routes, group, newSegments, outlet, false);
|
|
3784
|
+
}));
|
|
3785
|
+
}
|
|
3786
|
+
expandRegularSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet) {
|
|
3787
|
+
const { matched, consumedSegments, remainingSegments, positionalParamSegments } = match(segmentGroup, route, segments);
|
|
3788
|
+
if (!matched)
|
|
3789
|
+
return noMatch$1(segmentGroup);
|
|
3790
|
+
const newTree = this.applyRedirects.applyRedirectCommands(consumedSegments, route.redirectTo, positionalParamSegments);
|
|
3791
|
+
if (route.redirectTo.startsWith('/')) {
|
|
3792
|
+
return absoluteRedirect(newTree);
|
|
3793
|
+
}
|
|
3794
|
+
return this.applyRedirects.lineralizeSegments(route, newTree)
|
|
3795
|
+
.pipe(mergeMap((newSegments) => {
|
|
3796
|
+
return this.processSegment(injector, routes, segmentGroup, newSegments.concat(remainingSegments), outlet, false);
|
|
3797
|
+
}));
|
|
3798
|
+
}
|
|
3799
|
+
matchSegmentAgainstRoute(injector, rawSegment, route, segments, outlet, allowRedirects) {
|
|
3850
3800
|
let matchResult;
|
|
3851
3801
|
if (route.path === '**') {
|
|
3852
3802
|
const params = segments.length > 0 ? last(segments).parameters : {};
|
|
@@ -3856,6 +3806,11 @@ class Recognizer {
|
|
|
3856
3806
|
consumedSegments: [],
|
|
3857
3807
|
remainingSegments: [],
|
|
3858
3808
|
});
|
|
3809
|
+
// Prior versions of the route matching algorithm would stop matching at the wildcard route.
|
|
3810
|
+
// We should investigate a better strategy for any existing children. Otherwise, these
|
|
3811
|
+
// child segments are silently dropped from the navigation.
|
|
3812
|
+
// https://github.com/angular/angular/issues/40089
|
|
3813
|
+
rawSegment.children = {};
|
|
3859
3814
|
}
|
|
3860
3815
|
else {
|
|
3861
3816
|
matchResult =
|
|
@@ -3870,47 +3825,67 @@ class Recognizer {
|
|
|
3870
3825
|
}
|
|
3871
3826
|
return matchResult.pipe(switchMap((result) => {
|
|
3872
3827
|
if (result === null) {
|
|
3873
|
-
return
|
|
3828
|
+
return noMatch$1(rawSegment);
|
|
3874
3829
|
}
|
|
3875
|
-
const { snapshot, consumedSegments, remainingSegments } = result;
|
|
3876
3830
|
// If the route has an injector created from providers, we should start using that.
|
|
3877
3831
|
injector = route._injector ?? injector;
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3832
|
+
return this.getChildConfig(injector, route, segments)
|
|
3833
|
+
.pipe(switchMap(({ routes: childConfig }) => {
|
|
3834
|
+
const childInjector = route._loadedInjector ?? injector;
|
|
3835
|
+
const { snapshot, consumedSegments, remainingSegments } = result;
|
|
3836
|
+
const { segmentGroup, slicedSegments } = split(rawSegment, consumedSegments, remainingSegments, childConfig);
|
|
3837
|
+
if (slicedSegments.length === 0 && segmentGroup.hasChildren()) {
|
|
3838
|
+
return this.processChildren(childInjector, childConfig, segmentGroup)
|
|
3839
|
+
.pipe(map(children => {
|
|
3840
|
+
if (children === null) {
|
|
3841
|
+
return null;
|
|
3842
|
+
}
|
|
3843
|
+
return [new TreeNode(snapshot, children)];
|
|
3844
|
+
}));
|
|
3845
|
+
}
|
|
3846
|
+
if (childConfig.length === 0 && slicedSegments.length === 0) {
|
|
3847
|
+
return of([new TreeNode(snapshot, [])]);
|
|
3848
|
+
}
|
|
3849
|
+
const matchedOnOutlet = getOutlet(route) === outlet;
|
|
3850
|
+
// If we matched a config due to empty path match on a different outlet, we need to
|
|
3851
|
+
// continue passing the current outlet for the segment rather than switch to PRIMARY.
|
|
3852
|
+
// Note that we switch to primary when we have a match because outlet configs look like
|
|
3853
|
+
// this: {path: 'a', outlet: 'a', children: [
|
|
3854
|
+
// {path: 'b', component: B},
|
|
3855
|
+
// {path: 'c', component: C},
|
|
3856
|
+
// ]}
|
|
3857
|
+
// Notice that the children of the named outlet are configured with the primary outlet
|
|
3858
|
+
return this
|
|
3859
|
+
.processSegment(childInjector, childConfig, segmentGroup, slicedSegments, matchedOnOutlet ? PRIMARY_OUTLET : outlet, true)
|
|
3860
|
+
.pipe(map(children => {
|
|
3890
3861
|
return [new TreeNode(snapshot, children)];
|
|
3891
3862
|
}));
|
|
3863
|
+
}));
|
|
3864
|
+
}));
|
|
3865
|
+
}
|
|
3866
|
+
getChildConfig(injector, route, segments) {
|
|
3867
|
+
if (route.children) {
|
|
3868
|
+
// The children belong to the same module
|
|
3869
|
+
return of({ routes: route.children, injector });
|
|
3870
|
+
}
|
|
3871
|
+
if (route.loadChildren) {
|
|
3872
|
+
// lazy children belong to the loaded module
|
|
3873
|
+
if (route._loadedRoutes !== undefined) {
|
|
3874
|
+
return of({ routes: route._loadedRoutes, injector: route._loadedInjector });
|
|
3892
3875
|
}
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
// {path: 'b', component: B},
|
|
3902
|
-
// {path: 'c', component: C},
|
|
3903
|
-
// ]}
|
|
3904
|
-
// Notice that the children of the named outlet are configured with the primary outlet
|
|
3905
|
-
return this
|
|
3906
|
-
.processSegment(childInjector, childConfig, segmentGroup, slicedSegments, matchedOnOutlet ? PRIMARY_OUTLET : outlet)
|
|
3907
|
-
.pipe(map(children => {
|
|
3908
|
-
if (children === null) {
|
|
3909
|
-
return null;
|
|
3876
|
+
return runCanLoadGuards(injector, route, segments, this.urlSerializer)
|
|
3877
|
+
.pipe(mergeMap((shouldLoadResult) => {
|
|
3878
|
+
if (shouldLoadResult) {
|
|
3879
|
+
return this.configLoader.loadChildren(injector, route)
|
|
3880
|
+
.pipe(tap((cfg) => {
|
|
3881
|
+
route._loadedRoutes = cfg.routes;
|
|
3882
|
+
route._loadedInjector = cfg.injector;
|
|
3883
|
+
}));
|
|
3910
3884
|
}
|
|
3911
|
-
return
|
|
3885
|
+
return canLoadFails(route);
|
|
3912
3886
|
}));
|
|
3913
|
-
}
|
|
3887
|
+
}
|
|
3888
|
+
return of({ routes: [], injector });
|
|
3914
3889
|
}
|
|
3915
3890
|
}
|
|
3916
3891
|
function sortActivatedRouteSnapshots(nodes) {
|
|
@@ -3922,18 +3897,9 @@ function sortActivatedRouteSnapshots(nodes) {
|
|
|
3922
3897
|
return a.value.outlet.localeCompare(b.value.outlet);
|
|
3923
3898
|
});
|
|
3924
3899
|
}
|
|
3925
|
-
function getChildConfig(route) {
|
|
3926
|
-
if (route.children) {
|
|
3927
|
-
return route.children;
|
|
3928
|
-
}
|
|
3929
|
-
if (route.loadChildren) {
|
|
3930
|
-
return route._loadedRoutes;
|
|
3931
|
-
}
|
|
3932
|
-
return [];
|
|
3933
|
-
}
|
|
3934
3900
|
function hasEmptyPathConfig(node) {
|
|
3935
3901
|
const config = node.value.routeConfig;
|
|
3936
|
-
return config && config.path === ''
|
|
3902
|
+
return config && config.path === '';
|
|
3937
3903
|
}
|
|
3938
3904
|
/**
|
|
3939
3905
|
* Finds `TreeNode`s with matching empty path route configs and merges them into `TreeNode` with
|
|
@@ -3975,7 +3941,8 @@ function checkOutletNameUniqueness(nodes) {
|
|
|
3975
3941
|
if (routeWithSameOutletName) {
|
|
3976
3942
|
const p = routeWithSameOutletName.url.map(s => s.toString()).join('/');
|
|
3977
3943
|
const c = n.value.url.map(s => s.toString()).join('/');
|
|
3978
|
-
throw new ɵRuntimeError(4006 /* RuntimeErrorCode.TWO_SEGMENTS_WITH_SAME_OUTLET */,
|
|
3944
|
+
throw new ɵRuntimeError(4006 /* RuntimeErrorCode.TWO_SEGMENTS_WITH_SAME_OUTLET */, (typeof ngDevMode === 'undefined' || ngDevMode) &&
|
|
3945
|
+
`Two segments cannot have the same outlet name: '${p}' and '${c}'.`);
|
|
3979
3946
|
}
|
|
3980
3947
|
names[n.value.outlet] = n.value;
|
|
3981
3948
|
});
|
|
@@ -3987,9 +3954,11 @@ function getResolve(route) {
|
|
|
3987
3954
|
return route.resolve || {};
|
|
3988
3955
|
}
|
|
3989
3956
|
|
|
3990
|
-
function recognize(injector, rootComponentType, config, serializer, paramsInheritanceStrategy) {
|
|
3991
|
-
return mergeMap(t => recognize$1(injector, rootComponentType, config, t.
|
|
3992
|
-
.pipe(map(
|
|
3957
|
+
function recognize(injector, configLoader, rootComponentType, config, serializer, paramsInheritanceStrategy) {
|
|
3958
|
+
return mergeMap(t => recognize$1(injector, configLoader, rootComponentType, config, t.extractedUrl, serializer, paramsInheritanceStrategy)
|
|
3959
|
+
.pipe(map(({ state: targetSnapshot, tree: urlAfterRedirects }) => {
|
|
3960
|
+
return { ...t, targetSnapshot, urlAfterRedirects };
|
|
3961
|
+
})));
|
|
3993
3962
|
}
|
|
3994
3963
|
|
|
3995
3964
|
function resolveData(paramsInheritanceStrategy, injector) {
|
|
@@ -4060,7 +4029,6 @@ function switchTap(next) {
|
|
|
4060
4029
|
});
|
|
4061
4030
|
}
|
|
4062
4031
|
|
|
4063
|
-
const NG_DEV_MODE$5 = typeof ngDevMode === 'undefined' || !!ngDevMode;
|
|
4064
4032
|
/**
|
|
4065
4033
|
* The [DI token](guide/glossary/#di-token) for a router configuration.
|
|
4066
4034
|
*
|
|
@@ -4093,7 +4061,8 @@ class RouterConfigLoader {
|
|
|
4093
4061
|
if (this.onLoadEndListener) {
|
|
4094
4062
|
this.onLoadEndListener(route);
|
|
4095
4063
|
}
|
|
4096
|
-
|
|
4064
|
+
(typeof ngDevMode === 'undefined' || ngDevMode) &&
|
|
4065
|
+
assertStandalone(route.path ?? '', component);
|
|
4097
4066
|
route._loadedComponent = component;
|
|
4098
4067
|
}), finalize(() => {
|
|
4099
4068
|
this.componentLoaders.delete(route);
|
|
@@ -4136,7 +4105,8 @@ class RouterConfigLoader {
|
|
|
4136
4105
|
rawRoutes = injector.get(ROUTES, [], InjectFlags.Self | InjectFlags.Optional).flat();
|
|
4137
4106
|
}
|
|
4138
4107
|
const routes = rawRoutes.map(standardizeConfig);
|
|
4139
|
-
|
|
4108
|
+
(typeof ngDevMode === 'undefined' || ngDevMode) &&
|
|
4109
|
+
validateConfig(routes, route.path, requireStandaloneComponents);
|
|
4140
4110
|
return { routes, injector };
|
|
4141
4111
|
}), finalize(() => {
|
|
4142
4112
|
this.childrenLoaders.delete(route);
|
|
@@ -4158,10 +4128,10 @@ class RouterConfigLoader {
|
|
|
4158
4128
|
}
|
|
4159
4129
|
}));
|
|
4160
4130
|
}
|
|
4131
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: RouterConfigLoader, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4132
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: RouterConfigLoader, providedIn: 'root' }); }
|
|
4161
4133
|
}
|
|
4162
|
-
|
|
4163
|
-
RouterConfigLoader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.0-next.4", ngImport: i0, type: RouterConfigLoader, providedIn: 'root' });
|
|
4164
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.4", ngImport: i0, type: RouterConfigLoader, decorators: [{
|
|
4134
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: RouterConfigLoader, decorators: [{
|
|
4165
4135
|
type: Injectable,
|
|
4166
4136
|
args: [{ providedIn: 'root' }]
|
|
4167
4137
|
}] });
|
|
@@ -4177,7 +4147,6 @@ function maybeUnwrapDefaultExport(input) {
|
|
|
4177
4147
|
return isWrappedDefaultExport(input) ? input['default'] : input;
|
|
4178
4148
|
}
|
|
4179
4149
|
|
|
4180
|
-
const NG_DEV_MODE$4 = typeof ngDevMode === 'undefined' || !!ngDevMode;
|
|
4181
4150
|
class NavigationTransitions {
|
|
4182
4151
|
get hasRequestedNavigation() {
|
|
4183
4152
|
return this.navigationId !== 0;
|
|
@@ -4190,6 +4159,7 @@ class NavigationTransitions {
|
|
|
4190
4159
|
this.environmentInjector = inject(EnvironmentInjector);
|
|
4191
4160
|
this.urlSerializer = inject(UrlSerializer);
|
|
4192
4161
|
this.rootContexts = inject(ChildrenOutletContexts);
|
|
4162
|
+
this.inputBindingEnabled = inject(INPUT_BINDER, { optional: true }) !== null;
|
|
4193
4163
|
this.navigationId = 0;
|
|
4194
4164
|
/**
|
|
4195
4165
|
* Hook that enables you to pause navigation after the preactivation phase.
|
|
@@ -4267,7 +4237,7 @@ class NavigationTransitions {
|
|
|
4267
4237
|
browserUrlTree !== router.currentUrlTree.toString();
|
|
4268
4238
|
const onSameUrlNavigation = t.extras.onSameUrlNavigation ?? router.onSameUrlNavigation;
|
|
4269
4239
|
if (!urlTransition && onSameUrlNavigation !== 'reload') {
|
|
4270
|
-
const reason =
|
|
4240
|
+
const reason = (typeof ngDevMode === 'undefined' || ngDevMode) ?
|
|
4271
4241
|
`Navigation to ${t.rawUrl} was ignored because it is the same as the current Router URL.` :
|
|
4272
4242
|
'';
|
|
4273
4243
|
this.events.next(new NavigationSkipped(t.id, router.serializeUrl(overallTransitionState.rawUrl), reason, 0 /* NavigationSkippedCode.IgnoredSameUrlNavigation */));
|
|
@@ -4293,22 +4263,16 @@ class NavigationTransitions {
|
|
|
4293
4263
|
// navigation to always be async
|
|
4294
4264
|
return Promise.resolve(t);
|
|
4295
4265
|
}),
|
|
4296
|
-
//
|
|
4297
|
-
|
|
4298
|
-
// Update
|
|
4299
|
-
// `urlAfterRedirects` is guaranteed to be set after this point
|
|
4266
|
+
// Recognize
|
|
4267
|
+
recognize(this.environmentInjector, this.configLoader, this.rootComponentType, router.config, this.urlSerializer, router.paramsInheritanceStrategy),
|
|
4268
|
+
// Update URL if in `eager` update mode
|
|
4300
4269
|
tap(t => {
|
|
4270
|
+
overallTransitionState.targetSnapshot = t.targetSnapshot;
|
|
4271
|
+
overallTransitionState.urlAfterRedirects = t.urlAfterRedirects;
|
|
4301
4272
|
this.currentNavigation = {
|
|
4302
4273
|
...this.currentNavigation,
|
|
4303
4274
|
finalUrl: t.urlAfterRedirects
|
|
4304
4275
|
};
|
|
4305
|
-
overallTransitionState.urlAfterRedirects = t.urlAfterRedirects;
|
|
4306
|
-
}),
|
|
4307
|
-
// Recognize
|
|
4308
|
-
recognize(this.environmentInjector, this.rootComponentType, router.config, this.urlSerializer, router.paramsInheritanceStrategy),
|
|
4309
|
-
// Update URL if in `eager` update mode
|
|
4310
|
-
tap(t => {
|
|
4311
|
-
overallTransitionState.targetSnapshot = t.targetSnapshot;
|
|
4312
4276
|
if (router.urlUpdateStrategy === 'eager') {
|
|
4313
4277
|
if (!t.extras.skipLocationChange) {
|
|
4314
4278
|
const rawUrl = router.urlHandlingStrategy.merge(t.urlAfterRedirects, t.rawUrl);
|
|
@@ -4344,7 +4308,7 @@ class NavigationTransitions {
|
|
|
4344
4308
|
* current "settled" URL. This way the next navigation will be coming
|
|
4345
4309
|
* from the current URL in the browser.
|
|
4346
4310
|
*/
|
|
4347
|
-
const reason =
|
|
4311
|
+
const reason = (typeof ngDevMode === 'undefined' || ngDevMode) ?
|
|
4348
4312
|
`Navigation was ignored because the UrlHandlingStrategy` +
|
|
4349
4313
|
` indicated neither the current URL ${router.rawUrlTree} nor target URL ${t.rawUrl} should be processed.` :
|
|
4350
4314
|
'';
|
|
@@ -4392,7 +4356,7 @@ class NavigationTransitions {
|
|
|
4392
4356
|
complete: () => {
|
|
4393
4357
|
if (!dataResolved) {
|
|
4394
4358
|
router.restoreHistory(t);
|
|
4395
|
-
this.cancelNavigationTransition(t,
|
|
4359
|
+
this.cancelNavigationTransition(t, (typeof ngDevMode === 'undefined' || ngDevMode) ?
|
|
4396
4360
|
`At least one route resolver didn't emit any value.` :
|
|
4397
4361
|
'', 2 /* NavigationCancellationCode.NoDataFromResolver */);
|
|
4398
4362
|
}
|
|
@@ -4445,7 +4409,11 @@ class NavigationTransitions {
|
|
|
4445
4409
|
}
|
|
4446
4410
|
router.browserUrlTree = t.urlAfterRedirects;
|
|
4447
4411
|
}
|
|
4448
|
-
}), activateRoutes(this.rootContexts, router.routeReuseStrategy, (evt) => this.events.next(evt)),
|
|
4412
|
+
}), activateRoutes(this.rootContexts, router.routeReuseStrategy, (evt) => this.events.next(evt), this.inputBindingEnabled),
|
|
4413
|
+
// Ensure that if some observable used to drive the transition doesn't
|
|
4414
|
+
// complete, the navigation still finalizes This should never happen, but
|
|
4415
|
+
// this is done as a safety measure to avoid surfacing this error (#49567).
|
|
4416
|
+
take(1), tap({
|
|
4449
4417
|
next: (t) => {
|
|
4450
4418
|
completed = true;
|
|
4451
4419
|
this.lastSuccessfulNavigation = this.currentNavigation;
|
|
@@ -4465,7 +4433,7 @@ class NavigationTransitions {
|
|
|
4465
4433
|
* catch-all to make sure the NavigationCancel event is fired when a
|
|
4466
4434
|
* navigation gets cancelled but not caught by other means. */
|
|
4467
4435
|
if (!completed && !errored) {
|
|
4468
|
-
const cancelationReason =
|
|
4436
|
+
const cancelationReason = (typeof ngDevMode === 'undefined' || ngDevMode) ?
|
|
4469
4437
|
`Navigation ID ${overallTransitionState
|
|
4470
4438
|
.id} is not equal to the current navigation id ${this.navigationId}` :
|
|
4471
4439
|
'';
|
|
@@ -4539,10 +4507,10 @@ class NavigationTransitions {
|
|
|
4539
4507
|
this.events.next(navCancel);
|
|
4540
4508
|
t.resolve(false);
|
|
4541
4509
|
}
|
|
4510
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: NavigationTransitions, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4511
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: NavigationTransitions, providedIn: 'root' }); }
|
|
4542
4512
|
}
|
|
4543
|
-
|
|
4544
|
-
NavigationTransitions.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.0-next.4", ngImport: i0, type: NavigationTransitions, providedIn: 'root' });
|
|
4545
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.4", ngImport: i0, type: NavigationTransitions, decorators: [{
|
|
4513
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: NavigationTransitions, decorators: [{
|
|
4546
4514
|
type: Injectable,
|
|
4547
4515
|
args: [{ providedIn: 'root' }]
|
|
4548
4516
|
}], ctorParameters: function () { return []; } });
|
|
@@ -4593,10 +4561,10 @@ class TitleStrategy {
|
|
|
4593
4561
|
getResolvedTitleForRoute(snapshot) {
|
|
4594
4562
|
return snapshot.data[RouteTitleKey];
|
|
4595
4563
|
}
|
|
4564
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: TitleStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4565
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: TitleStrategy, providedIn: 'root', useFactory: () => inject(DefaultTitleStrategy) }); }
|
|
4596
4566
|
}
|
|
4597
|
-
|
|
4598
|
-
TitleStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.0-next.4", ngImport: i0, type: TitleStrategy, providedIn: 'root', useFactory: () => inject(DefaultTitleStrategy) });
|
|
4599
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.4", ngImport: i0, type: TitleStrategy, decorators: [{
|
|
4567
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: TitleStrategy, decorators: [{
|
|
4600
4568
|
type: Injectable,
|
|
4601
4569
|
args: [{ providedIn: 'root', useFactory: () => inject(DefaultTitleStrategy) }]
|
|
4602
4570
|
}] });
|
|
@@ -4619,10 +4587,10 @@ class DefaultTitleStrategy extends TitleStrategy {
|
|
|
4619
4587
|
this.title.setTitle(title);
|
|
4620
4588
|
}
|
|
4621
4589
|
}
|
|
4590
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: DefaultTitleStrategy, deps: [{ token: i1.Title }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4591
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: DefaultTitleStrategy, providedIn: 'root' }); }
|
|
4622
4592
|
}
|
|
4623
|
-
|
|
4624
|
-
DefaultTitleStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.0-next.4", ngImport: i0, type: DefaultTitleStrategy, providedIn: 'root' });
|
|
4625
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.4", ngImport: i0, type: DefaultTitleStrategy, decorators: [{
|
|
4593
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: DefaultTitleStrategy, decorators: [{
|
|
4626
4594
|
type: Injectable,
|
|
4627
4595
|
args: [{ providedIn: 'root' }]
|
|
4628
4596
|
}], ctorParameters: function () { return [{ type: i1.Title }]; } });
|
|
@@ -4635,10 +4603,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.4",
|
|
|
4635
4603
|
* @publicApi
|
|
4636
4604
|
*/
|
|
4637
4605
|
class RouteReuseStrategy {
|
|
4606
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: RouteReuseStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4607
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: RouteReuseStrategy, providedIn: 'root', useFactory: () => inject(DefaultRouteReuseStrategy) }); }
|
|
4638
4608
|
}
|
|
4639
|
-
|
|
4640
|
-
RouteReuseStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.0-next.4", ngImport: i0, type: RouteReuseStrategy, providedIn: 'root', useFactory: () => inject(DefaultRouteReuseStrategy) });
|
|
4641
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.4", ngImport: i0, type: RouteReuseStrategy, decorators: [{
|
|
4609
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: RouteReuseStrategy, decorators: [{
|
|
4642
4610
|
type: Injectable,
|
|
4643
4611
|
args: [{ providedIn: 'root', useFactory: () => inject(DefaultRouteReuseStrategy) }]
|
|
4644
4612
|
}] });
|
|
@@ -4689,21 +4657,20 @@ class BaseRouteReuseStrategy {
|
|
|
4689
4657
|
}
|
|
4690
4658
|
}
|
|
4691
4659
|
class DefaultRouteReuseStrategy extends BaseRouteReuseStrategy {
|
|
4660
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: DefaultRouteReuseStrategy, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4661
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: DefaultRouteReuseStrategy, providedIn: 'root' }); }
|
|
4692
4662
|
}
|
|
4693
|
-
|
|
4694
|
-
DefaultRouteReuseStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.0-next.4", ngImport: i0, type: DefaultRouteReuseStrategy, providedIn: 'root' });
|
|
4695
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.4", ngImport: i0, type: DefaultRouteReuseStrategy, decorators: [{
|
|
4663
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: DefaultRouteReuseStrategy, decorators: [{
|
|
4696
4664
|
type: Injectable,
|
|
4697
4665
|
args: [{ providedIn: 'root' }]
|
|
4698
4666
|
}] });
|
|
4699
4667
|
|
|
4700
|
-
const NG_DEV_MODE$3 = typeof ngDevMode === 'undefined' || !!ngDevMode;
|
|
4701
4668
|
/**
|
|
4702
4669
|
* A [DI token](guide/glossary/#di-token) for the router service.
|
|
4703
4670
|
*
|
|
4704
4671
|
* @publicApi
|
|
4705
4672
|
*/
|
|
4706
|
-
const ROUTER_CONFIGURATION = new InjectionToken(
|
|
4673
|
+
const ROUTER_CONFIGURATION = new InjectionToken((typeof ngDevMode === 'undefined' || ngDevMode) ? 'router config' : '', {
|
|
4707
4674
|
providedIn: 'root',
|
|
4708
4675
|
factory: () => ({}),
|
|
4709
4676
|
});
|
|
@@ -4716,10 +4683,10 @@ const ROUTER_CONFIGURATION = new InjectionToken(NG_DEV_MODE$3 ? 'router config'
|
|
|
4716
4683
|
* @publicApi
|
|
4717
4684
|
*/
|
|
4718
4685
|
class UrlHandlingStrategy {
|
|
4686
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: UrlHandlingStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4687
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: UrlHandlingStrategy, providedIn: 'root', useFactory: () => inject(DefaultUrlHandlingStrategy) }); }
|
|
4719
4688
|
}
|
|
4720
|
-
|
|
4721
|
-
UrlHandlingStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.0-next.4", ngImport: i0, type: UrlHandlingStrategy, providedIn: 'root', useFactory: () => inject(DefaultUrlHandlingStrategy) });
|
|
4722
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.4", ngImport: i0, type: UrlHandlingStrategy, decorators: [{
|
|
4689
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: UrlHandlingStrategy, decorators: [{
|
|
4723
4690
|
type: Injectable,
|
|
4724
4691
|
args: [{ providedIn: 'root', useFactory: () => inject(DefaultUrlHandlingStrategy) }]
|
|
4725
4692
|
}] });
|
|
@@ -4736,15 +4703,47 @@ class DefaultUrlHandlingStrategy {
|
|
|
4736
4703
|
merge(newUrlPart, wholeUrl) {
|
|
4737
4704
|
return newUrlPart;
|
|
4738
4705
|
}
|
|
4706
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: DefaultUrlHandlingStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4707
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: DefaultUrlHandlingStrategy, providedIn: 'root' }); }
|
|
4739
4708
|
}
|
|
4740
|
-
|
|
4741
|
-
DefaultUrlHandlingStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.0-next.4", ngImport: i0, type: DefaultUrlHandlingStrategy, providedIn: 'root' });
|
|
4742
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.4", ngImport: i0, type: DefaultUrlHandlingStrategy, decorators: [{
|
|
4709
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: DefaultUrlHandlingStrategy, decorators: [{
|
|
4743
4710
|
type: Injectable,
|
|
4744
4711
|
args: [{ providedIn: 'root' }]
|
|
4745
4712
|
}] });
|
|
4746
4713
|
|
|
4747
|
-
|
|
4714
|
+
var NavigationResult;
|
|
4715
|
+
(function (NavigationResult) {
|
|
4716
|
+
NavigationResult[NavigationResult["COMPLETE"] = 0] = "COMPLETE";
|
|
4717
|
+
NavigationResult[NavigationResult["FAILED"] = 1] = "FAILED";
|
|
4718
|
+
NavigationResult[NavigationResult["REDIRECTING"] = 2] = "REDIRECTING";
|
|
4719
|
+
})(NavigationResult || (NavigationResult = {}));
|
|
4720
|
+
/**
|
|
4721
|
+
* Performs the given action once the router finishes its next/current navigation.
|
|
4722
|
+
*
|
|
4723
|
+
* The navigation is considered complete under the following conditions:
|
|
4724
|
+
* - `NavigationCancel` event emits and the code is not `NavigationCancellationCode.Redirect` or
|
|
4725
|
+
* `NavigationCancellationCode.SupersededByNewNavigation`. In these cases, the
|
|
4726
|
+
* redirecting/superseding navigation must finish.
|
|
4727
|
+
* - `NavigationError`, `NavigationEnd`, or `NavigationSkipped` event emits
|
|
4728
|
+
*/
|
|
4729
|
+
function afterNextNavigation(router, action) {
|
|
4730
|
+
router.events
|
|
4731
|
+
.pipe(filter((e) => e instanceof NavigationEnd || e instanceof NavigationCancel ||
|
|
4732
|
+
e instanceof NavigationError || e instanceof NavigationSkipped), map(e => {
|
|
4733
|
+
if (e instanceof NavigationEnd || e instanceof NavigationSkipped) {
|
|
4734
|
+
return NavigationResult.COMPLETE;
|
|
4735
|
+
}
|
|
4736
|
+
const redirecting = e instanceof NavigationCancel ?
|
|
4737
|
+
(e.code === 0 /* NavigationCancellationCode.Redirect */ ||
|
|
4738
|
+
e.code === 1 /* NavigationCancellationCode.SupersededByNewNavigation */) :
|
|
4739
|
+
false;
|
|
4740
|
+
return redirecting ? NavigationResult.REDIRECTING : NavigationResult.FAILED;
|
|
4741
|
+
}), filter((result) => result !== NavigationResult.REDIRECTING), take(1))
|
|
4742
|
+
.subscribe(() => {
|
|
4743
|
+
action();
|
|
4744
|
+
});
|
|
4745
|
+
}
|
|
4746
|
+
|
|
4748
4747
|
function defaultErrorHandler(error) {
|
|
4749
4748
|
throw error;
|
|
4750
4749
|
}
|
|
@@ -4821,6 +4820,7 @@ class Router {
|
|
|
4821
4820
|
this.console = inject(ɵConsole);
|
|
4822
4821
|
this.isNgZoneEnabled = false;
|
|
4823
4822
|
this.options = inject(ROUTER_CONFIGURATION, { optional: true }) || {};
|
|
4823
|
+
this.pendingTasks = inject(ɵInitialRenderPendingTasks);
|
|
4824
4824
|
/**
|
|
4825
4825
|
* A handler for navigation errors in this NgModule.
|
|
4826
4826
|
*
|
|
@@ -4937,6 +4937,13 @@ class Router {
|
|
|
4937
4937
|
this.navigationTransitions = inject(NavigationTransitions);
|
|
4938
4938
|
this.urlSerializer = inject(UrlSerializer);
|
|
4939
4939
|
this.location = inject(Location);
|
|
4940
|
+
/**
|
|
4941
|
+
* Indicates whether the the application has opted in to binding Router data to component inputs.
|
|
4942
|
+
*
|
|
4943
|
+
* This option is enabled by the `withComponentInputBinding` feature of `provideRouter` or
|
|
4944
|
+
* `bindToComponentInputs` in the `ExtraOptions` of `RouterModule.forRoot`.
|
|
4945
|
+
*/
|
|
4946
|
+
this.componentInputBindingEnabled = !!inject(INPUT_BINDER, { optional: true });
|
|
4940
4947
|
this.isNgZoneEnabled = inject(NgZone) instanceof NgZone && NgZone.isInAngularZone();
|
|
4941
4948
|
this.resetConfig(this.config);
|
|
4942
4949
|
this.currentUrlTree = new UrlTree();
|
|
@@ -5054,7 +5061,7 @@ class Router {
|
|
|
5054
5061
|
* ```
|
|
5055
5062
|
*/
|
|
5056
5063
|
resetConfig(config) {
|
|
5057
|
-
|
|
5064
|
+
(typeof ngDevMode === 'undefined' || ngDevMode) && validateConfig(config);
|
|
5058
5065
|
this.config = config.map(standardizeConfig);
|
|
5059
5066
|
this.navigated = false;
|
|
5060
5067
|
this.lastSuccessfulId = -1;
|
|
@@ -5189,13 +5196,10 @@ class Router {
|
|
|
5189
5196
|
navigateByUrl(url, extras = {
|
|
5190
5197
|
skipLocationChange: false
|
|
5191
5198
|
}) {
|
|
5192
|
-
if (
|
|
5199
|
+
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
5193
5200
|
if (this.isNgZoneEnabled && !NgZone.isInAngularZone()) {
|
|
5194
5201
|
this.console.warn(`Navigation triggered outside Angular zone, did you forget to call 'ngZone.run()'?`);
|
|
5195
5202
|
}
|
|
5196
|
-
if (url instanceof UrlTree && url._warnIfUsedForNavigation) {
|
|
5197
|
-
this.console.warn(url._warnIfUsedForNavigation);
|
|
5198
|
-
}
|
|
5199
5203
|
}
|
|
5200
5204
|
const urlTree = isUrlTree(url) ? url : this.parseUrl(url);
|
|
5201
5205
|
const mergedTree = this.urlHandlingStrategy.merge(urlTree, this.rawUrlTree);
|
|
@@ -5318,6 +5322,13 @@ class Router {
|
|
|
5318
5322
|
// This is unused when `canceledNavigationResolution` is not computed.
|
|
5319
5323
|
targetPageId = 0;
|
|
5320
5324
|
}
|
|
5325
|
+
// Indicate that the navigation is happening.
|
|
5326
|
+
const taskId = this.pendingTasks.add();
|
|
5327
|
+
afterNextNavigation(this, () => {
|
|
5328
|
+
// Remove pending task in a microtask to allow for cancelled
|
|
5329
|
+
// initial navigations and redirects within the same task.
|
|
5330
|
+
Promise.resolve().then(() => this.pendingTasks.remove(taskId));
|
|
5331
|
+
});
|
|
5321
5332
|
this.navigationTransitions.handleNavigationRequest({
|
|
5322
5333
|
targetPageId,
|
|
5323
5334
|
source,
|
|
@@ -5416,10 +5427,10 @@ class Router {
|
|
|
5416
5427
|
}
|
|
5417
5428
|
return { navigationId };
|
|
5418
5429
|
}
|
|
5430
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: Router, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
5431
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: Router, providedIn: 'root' }); }
|
|
5419
5432
|
}
|
|
5420
|
-
|
|
5421
|
-
Router.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.0-next.4", ngImport: i0, type: Router, providedIn: 'root' });
|
|
5422
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.4", ngImport: i0, type: Router, decorators: [{
|
|
5433
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: Router, decorators: [{
|
|
5423
5434
|
type: Injectable,
|
|
5424
5435
|
args: [{ providedIn: 'root' }]
|
|
5425
5436
|
}], ctorParameters: function () { return []; } });
|
|
@@ -5427,7 +5438,8 @@ function validateCommands(commands) {
|
|
|
5427
5438
|
for (let i = 0; i < commands.length; i++) {
|
|
5428
5439
|
const cmd = commands[i];
|
|
5429
5440
|
if (cmd == null) {
|
|
5430
|
-
throw new ɵRuntimeError(4008 /* RuntimeErrorCode.NULLISH_COMMAND */,
|
|
5441
|
+
throw new ɵRuntimeError(4008 /* RuntimeErrorCode.NULLISH_COMMAND */, (typeof ngDevMode === 'undefined' || ngDevMode) &&
|
|
5442
|
+
`The requested path contains ${cmd} segment at index ${i}`);
|
|
5431
5443
|
}
|
|
5432
5444
|
}
|
|
5433
5445
|
}
|
|
@@ -5704,10 +5716,10 @@ class RouterLink {
|
|
|
5704
5716
|
preserveFragment: this.preserveFragment,
|
|
5705
5717
|
});
|
|
5706
5718
|
}
|
|
5719
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0-next.6", 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 }); }
|
|
5720
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.0-next.6", 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 }); }
|
|
5707
5721
|
}
|
|
5708
|
-
|
|
5709
|
-
RouterLink.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.0-next.4", 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 });
|
|
5710
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.4", ngImport: i0, type: RouterLink, decorators: [{
|
|
5722
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: RouterLink, decorators: [{
|
|
5711
5723
|
type: Directive,
|
|
5712
5724
|
args: [{
|
|
5713
5725
|
selector: '[routerLink]',
|
|
@@ -5927,10 +5939,10 @@ class RouterLinkActive {
|
|
|
5927
5939
|
const isActiveCheckFn = this.isLinkActive(this.router);
|
|
5928
5940
|
return this.link && isActiveCheckFn(this.link) || this.links.some(isActiveCheckFn);
|
|
5929
5941
|
}
|
|
5942
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: RouterLinkActive, deps: [{ token: Router }, { token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }, { token: RouterLink, optional: true }], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
5943
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.0-next.6", 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 }); }
|
|
5930
5944
|
}
|
|
5931
|
-
|
|
5932
|
-
RouterLinkActive.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.0-next.4", 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 });
|
|
5933
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.4", ngImport: i0, type: RouterLinkActive, decorators: [{
|
|
5945
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: RouterLinkActive, decorators: [{
|
|
5934
5946
|
type: Directive,
|
|
5935
5947
|
args: [{
|
|
5936
5948
|
selector: '[routerLinkActive]',
|
|
@@ -5982,10 +5994,10 @@ class PreloadAllModules {
|
|
|
5982
5994
|
preload(route, fn) {
|
|
5983
5995
|
return fn().pipe(catchError(() => of(null)));
|
|
5984
5996
|
}
|
|
5997
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: PreloadAllModules, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
5998
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: PreloadAllModules, providedIn: 'root' }); }
|
|
5985
5999
|
}
|
|
5986
|
-
|
|
5987
|
-
PreloadAllModules.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.0-next.4", ngImport: i0, type: PreloadAllModules, providedIn: 'root' });
|
|
5988
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.4", ngImport: i0, type: PreloadAllModules, decorators: [{
|
|
6000
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: PreloadAllModules, decorators: [{
|
|
5989
6001
|
type: Injectable,
|
|
5990
6002
|
args: [{ providedIn: 'root' }]
|
|
5991
6003
|
}] });
|
|
@@ -6002,10 +6014,10 @@ class NoPreloading {
|
|
|
6002
6014
|
preload(route, fn) {
|
|
6003
6015
|
return of(null);
|
|
6004
6016
|
}
|
|
6017
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: NoPreloading, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
6018
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: NoPreloading, providedIn: 'root' }); }
|
|
6005
6019
|
}
|
|
6006
|
-
|
|
6007
|
-
NoPreloading.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.0-next.4", ngImport: i0, type: NoPreloading, providedIn: 'root' });
|
|
6008
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.4", ngImport: i0, type: NoPreloading, decorators: [{
|
|
6020
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: NoPreloading, decorators: [{
|
|
6009
6021
|
type: Injectable,
|
|
6010
6022
|
args: [{ providedIn: 'root' }]
|
|
6011
6023
|
}] });
|
|
@@ -6064,7 +6076,7 @@ class RouterPreloader {
|
|
|
6064
6076
|
(route.loadComponent && !route._loadedComponent)) {
|
|
6065
6077
|
res.push(this.preloadConfig(injectorForCurrentRoute, route));
|
|
6066
6078
|
}
|
|
6067
|
-
|
|
6079
|
+
if (route.children || route._loadedRoutes) {
|
|
6068
6080
|
res.push(this.processRoutes(injectorForChildren, (route.children ?? route._loadedRoutes)));
|
|
6069
6081
|
}
|
|
6070
6082
|
}
|
|
@@ -6098,10 +6110,10 @@ class RouterPreloader {
|
|
|
6098
6110
|
}
|
|
6099
6111
|
});
|
|
6100
6112
|
}
|
|
6113
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: RouterPreloader, deps: [{ token: Router }, { token: i0.Compiler }, { token: i0.EnvironmentInjector }, { token: PreloadingStrategy }, { token: RouterConfigLoader }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
6114
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: RouterPreloader, providedIn: 'root' }); }
|
|
6101
6115
|
}
|
|
6102
|
-
|
|
6103
|
-
RouterPreloader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.0-next.4", ngImport: i0, type: RouterPreloader, providedIn: 'root' });
|
|
6104
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.4", ngImport: i0, type: RouterPreloader, decorators: [{
|
|
6116
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: RouterPreloader, decorators: [{
|
|
6105
6117
|
type: Injectable,
|
|
6106
6118
|
args: [{ providedIn: 'root' }]
|
|
6107
6119
|
}], ctorParameters: function () { return [{ type: Router }, { type: i0.Compiler }, { type: i0.EnvironmentInjector }, { type: PreloadingStrategy }, { type: RouterConfigLoader }]; } });
|
|
@@ -6194,47 +6206,13 @@ class RouterScroller {
|
|
|
6194
6206
|
this.routerEventsSubscription?.unsubscribe();
|
|
6195
6207
|
this.scrollEventsSubscription?.unsubscribe();
|
|
6196
6208
|
}
|
|
6209
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: RouterScroller, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
6210
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: RouterScroller }); }
|
|
6197
6211
|
}
|
|
6198
|
-
|
|
6199
|
-
RouterScroller.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.0-next.4", ngImport: i0, type: RouterScroller });
|
|
6200
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.4", ngImport: i0, type: RouterScroller, decorators: [{
|
|
6212
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: RouterScroller, decorators: [{
|
|
6201
6213
|
type: Injectable
|
|
6202
6214
|
}], ctorParameters: function () { return [{ type: UrlSerializer }, { type: NavigationTransitions }, { type: i3.ViewportScroller }, { type: i0.NgZone }, { type: undefined }]; } });
|
|
6203
6215
|
|
|
6204
|
-
var NavigationResult;
|
|
6205
|
-
(function (NavigationResult) {
|
|
6206
|
-
NavigationResult[NavigationResult["COMPLETE"] = 0] = "COMPLETE";
|
|
6207
|
-
NavigationResult[NavigationResult["FAILED"] = 1] = "FAILED";
|
|
6208
|
-
NavigationResult[NavigationResult["REDIRECTING"] = 2] = "REDIRECTING";
|
|
6209
|
-
})(NavigationResult || (NavigationResult = {}));
|
|
6210
|
-
/**
|
|
6211
|
-
* Performs the given action once the router finishes its next/current navigation.
|
|
6212
|
-
*
|
|
6213
|
-
* The navigation is considered complete under the following conditions:
|
|
6214
|
-
* - `NavigationCancel` event emits and the code is not `NavigationCancellationCode.Redirect` or
|
|
6215
|
-
* `NavigationCancellationCode.SupersededByNewNavigation`. In these cases, the
|
|
6216
|
-
* redirecting/superseding navigation must finish.
|
|
6217
|
-
* - `NavigationError`, `NavigationEnd`, or `NavigationSkipped` event emits
|
|
6218
|
-
*/
|
|
6219
|
-
function afterNextNavigation(router, action) {
|
|
6220
|
-
router.events
|
|
6221
|
-
.pipe(filter((e) => e instanceof NavigationEnd || e instanceof NavigationCancel ||
|
|
6222
|
-
e instanceof NavigationError || e instanceof NavigationSkipped), map(e => {
|
|
6223
|
-
if (e instanceof NavigationEnd || e instanceof NavigationSkipped) {
|
|
6224
|
-
return NavigationResult.COMPLETE;
|
|
6225
|
-
}
|
|
6226
|
-
const redirecting = e instanceof NavigationCancel ?
|
|
6227
|
-
(e.code === 0 /* NavigationCancellationCode.Redirect */ ||
|
|
6228
|
-
e.code === 1 /* NavigationCancellationCode.SupersededByNewNavigation */) :
|
|
6229
|
-
false;
|
|
6230
|
-
return redirecting ? NavigationResult.REDIRECTING : NavigationResult.FAILED;
|
|
6231
|
-
}), filter((result) => result !== NavigationResult.REDIRECTING), take(1))
|
|
6232
|
-
.subscribe(() => {
|
|
6233
|
-
action();
|
|
6234
|
-
});
|
|
6235
|
-
}
|
|
6236
|
-
|
|
6237
|
-
const NG_DEV_MODE$1 = typeof ngDevMode === 'undefined' || ngDevMode;
|
|
6238
6216
|
/**
|
|
6239
6217
|
* Sets up providers necessary to enable `Router` functionality for the application.
|
|
6240
6218
|
* Allows to configure a set of routes as well as extra features that should be enabled.
|
|
@@ -6274,7 +6252,9 @@ const NG_DEV_MODE$1 = typeof ngDevMode === 'undefined' || ngDevMode;
|
|
|
6274
6252
|
function provideRouter(routes, ...features) {
|
|
6275
6253
|
return makeEnvironmentProviders([
|
|
6276
6254
|
{ provide: ROUTES, multi: true, useValue: routes },
|
|
6277
|
-
|
|
6255
|
+
(typeof ngDevMode === 'undefined' || ngDevMode) ?
|
|
6256
|
+
{ provide: ROUTER_IS_PROVIDED, useValue: true } :
|
|
6257
|
+
[],
|
|
6278
6258
|
{ provide: ActivatedRoute, useFactory: rootRoute, deps: [Router] },
|
|
6279
6259
|
{ provide: APP_BOOTSTRAP_LISTENER, multi: true, useFactory: getBootstrapListener },
|
|
6280
6260
|
features.map(feature => feature.ɵproviders),
|
|
@@ -6326,7 +6306,7 @@ const routerIsProvidedDevModeCheck = {
|
|
|
6326
6306
|
function provideRoutes(routes) {
|
|
6327
6307
|
return [
|
|
6328
6308
|
{ provide: ROUTES, multi: true, useValue: routes },
|
|
6329
|
-
|
|
6309
|
+
(typeof ngDevMode === 'undefined' || ngDevMode) ? routerIsProvidedDevModeCheck : [],
|
|
6330
6310
|
];
|
|
6331
6311
|
}
|
|
6332
6312
|
/**
|
|
@@ -6384,6 +6364,7 @@ function getBootstrapListener() {
|
|
|
6384
6364
|
router.resetRootComponentType(ref.componentTypes[0]);
|
|
6385
6365
|
if (!bootstrapDone.closed) {
|
|
6386
6366
|
bootstrapDone.next();
|
|
6367
|
+
bootstrapDone.complete();
|
|
6387
6368
|
bootstrapDone.unsubscribe();
|
|
6388
6369
|
}
|
|
6389
6370
|
};
|
|
@@ -6393,12 +6374,12 @@ function getBootstrapListener() {
|
|
|
6393
6374
|
* `enabledBlocking`, the first navigation waits until bootstrapping is finished before continuing
|
|
6394
6375
|
* to the activation phase.
|
|
6395
6376
|
*/
|
|
6396
|
-
const BOOTSTRAP_DONE = new InjectionToken(
|
|
6377
|
+
const BOOTSTRAP_DONE = new InjectionToken((typeof ngDevMode === 'undefined' || ngDevMode) ? 'bootstrap done indicator' : '', {
|
|
6397
6378
|
factory: () => {
|
|
6398
6379
|
return new Subject();
|
|
6399
6380
|
}
|
|
6400
6381
|
});
|
|
6401
|
-
const INITIAL_NAVIGATION = new InjectionToken(
|
|
6382
|
+
const INITIAL_NAVIGATION = new InjectionToken((typeof ngDevMode === 'undefined' || ngDevMode) ? 'initial navigation' : '', { providedIn: 'root', factory: () => 1 /* InitialNavigation.EnabledNonBlocking */ });
|
|
6402
6383
|
/**
|
|
6403
6384
|
* Configures initial navigation to start before the root component is created.
|
|
6404
6385
|
*
|
|
@@ -6527,7 +6508,7 @@ function withDisabledInitialNavigation() {
|
|
|
6527
6508
|
*/
|
|
6528
6509
|
function withDebugTracing() {
|
|
6529
6510
|
let providers = [];
|
|
6530
|
-
if (
|
|
6511
|
+
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
6531
6512
|
providers = [{
|
|
6532
6513
|
provide: ENVIRONMENT_INITIALIZER,
|
|
6533
6514
|
multi: true,
|
|
@@ -6549,7 +6530,7 @@ function withDebugTracing() {
|
|
|
6549
6530
|
}
|
|
6550
6531
|
return routerFeature(1 /* RouterFeatureKind.DebugTracingFeature */, providers);
|
|
6551
6532
|
}
|
|
6552
|
-
const ROUTER_PRELOADER = new InjectionToken(
|
|
6533
|
+
const ROUTER_PRELOADER = new InjectionToken((typeof ngDevMode === 'undefined' || ngDevMode) ? 'router preloader' : '');
|
|
6553
6534
|
/**
|
|
6554
6535
|
* Allows to configure a preloading strategy to use. The strategy is configured by providing a
|
|
6555
6536
|
* reference to a class that implements a `PreloadingStrategy`.
|
|
@@ -6690,8 +6671,34 @@ function withNavigationErrorHandler(fn) {
|
|
|
6690
6671
|
}];
|
|
6691
6672
|
return routerFeature(7 /* RouterFeatureKind.NavigationErrorHandlerFeature */, providers);
|
|
6692
6673
|
}
|
|
6674
|
+
/**
|
|
6675
|
+
* Enables binding information from the `Router` state directly to the inputs of the component in
|
|
6676
|
+
* `Route` configurations.
|
|
6677
|
+
*
|
|
6678
|
+
* @usageNotes
|
|
6679
|
+
*
|
|
6680
|
+
* Basic example of how you can enable the feature:
|
|
6681
|
+
* ```
|
|
6682
|
+
* const appRoutes: Routes = [];
|
|
6683
|
+
* bootstrapApplication(AppComponent,
|
|
6684
|
+
* {
|
|
6685
|
+
* providers: [
|
|
6686
|
+
* provideRouter(appRoutes, withComponentInputBinding())
|
|
6687
|
+
* ]
|
|
6688
|
+
* }
|
|
6689
|
+
* );
|
|
6690
|
+
* ```
|
|
6691
|
+
*
|
|
6692
|
+
* @returns A set of providers for use with `provideRouter`.
|
|
6693
|
+
*/
|
|
6694
|
+
function withComponentInputBinding() {
|
|
6695
|
+
const providers = [
|
|
6696
|
+
RoutedComponentInputBinder,
|
|
6697
|
+
{ provide: INPUT_BINDER, useExisting: RoutedComponentInputBinder },
|
|
6698
|
+
];
|
|
6699
|
+
return routerFeature(8 /* RouterFeatureKind.ComponentInputBindingFeature */, providers);
|
|
6700
|
+
}
|
|
6693
6701
|
|
|
6694
|
-
const NG_DEV_MODE = typeof ngDevMode === 'undefined' || ngDevMode;
|
|
6695
6702
|
/**
|
|
6696
6703
|
* The directives defined in the `RouterModule`.
|
|
6697
6704
|
*/
|
|
@@ -6699,7 +6706,8 @@ const ROUTER_DIRECTIVES = [RouterOutlet, RouterLink, RouterLinkActive, ɵEmptyOu
|
|
|
6699
6706
|
/**
|
|
6700
6707
|
* @docsNotRequired
|
|
6701
6708
|
*/
|
|
6702
|
-
const ROUTER_FORROOT_GUARD = new InjectionToken(
|
|
6709
|
+
const ROUTER_FORROOT_GUARD = new InjectionToken((typeof ngDevMode === 'undefined' || ngDevMode) ? 'router duplicate forRoot guard' :
|
|
6710
|
+
'ROUTER_FORROOT_GUARD');
|
|
6703
6711
|
// TODO(atscott): All of these except `ActivatedRoute` are `providedIn: 'root'`. They are only kept
|
|
6704
6712
|
// here to avoid a breaking change whereby the provider order matters based on where the
|
|
6705
6713
|
// `RouterModule`/`RouterTestingModule` is imported. These can/should be removed as a "breaking"
|
|
@@ -6713,7 +6721,8 @@ const ROUTER_PROVIDERS = [
|
|
|
6713
6721
|
RouterConfigLoader,
|
|
6714
6722
|
// Only used to warn when `provideRoutes` is used without `RouterModule` or `provideRouter`. Can
|
|
6715
6723
|
// be removed when `provideRoutes` is removed.
|
|
6716
|
-
|
|
6724
|
+
(typeof ngDevMode === 'undefined' || ngDevMode) ? { provide: ROUTER_IS_PROVIDED, useValue: true } :
|
|
6725
|
+
[],
|
|
6717
6726
|
];
|
|
6718
6727
|
function routerNgProbeToken() {
|
|
6719
6728
|
return new NgProbeToken('Router', Router);
|
|
@@ -6764,7 +6773,9 @@ class RouterModule {
|
|
|
6764
6773
|
ngModule: RouterModule,
|
|
6765
6774
|
providers: [
|
|
6766
6775
|
ROUTER_PROVIDERS,
|
|
6767
|
-
|
|
6776
|
+
(typeof ngDevMode === 'undefined' || ngDevMode) ?
|
|
6777
|
+
(config?.enableTracing ? withDebugTracing().ɵproviders : []) :
|
|
6778
|
+
[],
|
|
6768
6779
|
{ provide: ROUTES, multi: true, useValue: routes },
|
|
6769
6780
|
{
|
|
6770
6781
|
provide: ROUTER_FORROOT_GUARD,
|
|
@@ -6777,6 +6788,7 @@ class RouterModule {
|
|
|
6777
6788
|
config?.preloadingStrategy ? withPreloading(config.preloadingStrategy).ɵproviders : [],
|
|
6778
6789
|
{ provide: NgProbeToken, multi: true, useFactory: routerNgProbeToken },
|
|
6779
6790
|
config?.initialNavigation ? provideInitialNavigation(config) : [],
|
|
6791
|
+
config?.bindToComponentInputs ? withComponentInputBinding().ɵproviders : [],
|
|
6780
6792
|
provideRouterInitializer(),
|
|
6781
6793
|
],
|
|
6782
6794
|
};
|
|
@@ -6803,11 +6815,11 @@ class RouterModule {
|
|
|
6803
6815
|
providers: [{ provide: ROUTES, multi: true, useValue: routes }],
|
|
6804
6816
|
};
|
|
6805
6817
|
}
|
|
6818
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: RouterModule, deps: [{ token: ROUTER_FORROOT_GUARD, optional: true }], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
6819
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.0.0-next.6", ngImport: i0, type: RouterModule, imports: [RouterOutlet, RouterLink, RouterLinkActive, ɵEmptyOutletComponent], exports: [RouterOutlet, RouterLink, RouterLinkActive, ɵEmptyOutletComponent] }); }
|
|
6820
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: RouterModule, imports: [ɵEmptyOutletComponent] }); }
|
|
6806
6821
|
}
|
|
6807
|
-
|
|
6808
|
-
RouterModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.0.0-next.4", ngImport: i0, type: RouterModule, imports: [RouterOutlet, RouterLink, RouterLinkActive, ɵEmptyOutletComponent], exports: [RouterOutlet, RouterLink, RouterLinkActive, ɵEmptyOutletComponent] });
|
|
6809
|
-
RouterModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.0.0-next.4", ngImport: i0, type: RouterModule, imports: [ɵEmptyOutletComponent] });
|
|
6810
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.4", ngImport: i0, type: RouterModule, decorators: [{
|
|
6822
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.6", ngImport: i0, type: RouterModule, decorators: [{
|
|
6811
6823
|
type: NgModule,
|
|
6812
6824
|
args: [{
|
|
6813
6825
|
imports: ROUTER_DIRECTIVES,
|
|
@@ -6850,7 +6862,7 @@ function providePathLocationStrategy() {
|
|
|
6850
6862
|
return { provide: LocationStrategy, useClass: PathLocationStrategy };
|
|
6851
6863
|
}
|
|
6852
6864
|
function provideForRootGuard(router) {
|
|
6853
|
-
if (
|
|
6865
|
+
if ((typeof ngDevMode === 'undefined' || ngDevMode) && router) {
|
|
6854
6866
|
throw new ɵRuntimeError(4007 /* RuntimeErrorCode.FOR_ROOT_CALLED_TWICE */, `The Router was provided more than once. This can happen if 'forRoot' is used outside of the root injector.` +
|
|
6855
6867
|
` Lazy loaded modules should use RouterModule.forChild() instead.`);
|
|
6856
6868
|
}
|
|
@@ -6873,7 +6885,7 @@ function provideInitialNavigation(config) {
|
|
|
6873
6885
|
*
|
|
6874
6886
|
* @publicApi
|
|
6875
6887
|
*/
|
|
6876
|
-
const ROUTER_INITIALIZER = new InjectionToken(
|
|
6888
|
+
const ROUTER_INITIALIZER = new InjectionToken((typeof ngDevMode === 'undefined' || ngDevMode) ? 'Router Initializer' : '');
|
|
6877
6889
|
function provideRouterInitializer() {
|
|
6878
6890
|
return [
|
|
6879
6891
|
// ROUTER_INITIALIZER token should be removed. It's public API but shouldn't be. We can just
|
|
@@ -6952,7 +6964,7 @@ function mapToResolve(provider) {
|
|
|
6952
6964
|
/**
|
|
6953
6965
|
* @publicApi
|
|
6954
6966
|
*/
|
|
6955
|
-
const VERSION = new Version('16.0.0-next.
|
|
6967
|
+
const VERSION = new Version('16.0.0-next.6');
|
|
6956
6968
|
|
|
6957
6969
|
/**
|
|
6958
6970
|
* @module
|
|
@@ -6967,5 +6979,5 @@ const VERSION = new Version('16.0.0-next.4');
|
|
|
6967
6979
|
* Generated bundle index. Do not edit.
|
|
6968
6980
|
*/
|
|
6969
6981
|
|
|
6970
|
-
export { ActivatedRoute, ActivatedRouteSnapshot, ActivationEnd, ActivationStart, BaseRouteReuseStrategy, ChildActivationEnd, ChildActivationStart, ChildrenOutletContexts, DefaultTitleStrategy, DefaultUrlSerializer, GuardsCheckEnd, GuardsCheckStart, NavigationCancel, NavigationEnd, NavigationError, NavigationSkipped, NavigationStart, NoPreloading, OutletContext, PRIMARY_OUTLET, PreloadAllModules, PreloadingStrategy, ROUTER_CONFIGURATION, ROUTER_INITIALIZER, ROUTES, ResolveEnd, ResolveStart, RouteConfigLoadEnd, RouteConfigLoadStart, RouteReuseStrategy, Router, RouterEvent, RouterLink, RouterLinkActive, RouterLink as RouterLinkWithHref, RouterModule, RouterOutlet, RouterPreloader, RouterState, RouterStateSnapshot, RoutesRecognized, Scroll, TitleStrategy, UrlHandlingStrategy, UrlSegment, UrlSegmentGroup, UrlSerializer, UrlTree, VERSION, convertToParamMap, createUrlTreeFromSnapshot, defaultUrlMatcher, mapToCanActivate, mapToCanActivateChild, mapToCanDeactivate, mapToCanMatch, mapToResolve, provideRouter, provideRoutes, withDebugTracing, withDisabledInitialNavigation, withEnabledBlockingInitialNavigation, withHashLocation, withInMemoryScrolling, withNavigationErrorHandler, withPreloading, withRouterConfig, ɵEmptyOutletComponent, ROUTER_PROVIDERS as ɵROUTER_PROVIDERS, afterNextNavigation as ɵafterNextNavigation, withPreloading as ɵwithPreloading };
|
|
6982
|
+
export { ActivatedRoute, ActivatedRouteSnapshot, ActivationEnd, ActivationStart, BaseRouteReuseStrategy, ChildActivationEnd, ChildActivationStart, ChildrenOutletContexts, DefaultTitleStrategy, DefaultUrlSerializer, GuardsCheckEnd, GuardsCheckStart, NavigationCancel, NavigationEnd, NavigationError, NavigationSkipped, NavigationStart, NoPreloading, OutletContext, PRIMARY_OUTLET, PreloadAllModules, PreloadingStrategy, ROUTER_CONFIGURATION, ROUTER_INITIALIZER, ROUTES, ResolveEnd, ResolveStart, RouteConfigLoadEnd, RouteConfigLoadStart, RouteReuseStrategy, Router, RouterEvent, RouterLink, RouterLinkActive, RouterLink as RouterLinkWithHref, RouterModule, RouterOutlet, RouterPreloader, RouterState, RouterStateSnapshot, RoutesRecognized, Scroll, TitleStrategy, UrlHandlingStrategy, UrlSegment, UrlSegmentGroup, UrlSerializer, UrlTree, VERSION, convertToParamMap, createUrlTreeFromSnapshot, defaultUrlMatcher, mapToCanActivate, mapToCanActivateChild, mapToCanDeactivate, mapToCanMatch, mapToResolve, provideRouter, provideRoutes, withComponentInputBinding, withDebugTracing, withDisabledInitialNavigation, withEnabledBlockingInitialNavigation, withHashLocation, withInMemoryScrolling, withNavigationErrorHandler, withPreloading, withRouterConfig, ɵEmptyOutletComponent, ROUTER_PROVIDERS as ɵROUTER_PROVIDERS, afterNextNavigation as ɵafterNextNavigation, withPreloading as ɵwithPreloading };
|
|
6971
6983
|
//# sourceMappingURL=router.mjs.map
|