@angular/router 14.0.0-next.12 → 14.0.0-next.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2020/src/apply_redirects.mjs +57 -47
- package/esm2020/src/components/empty_outlet.mjs +3 -3
- package/esm2020/src/create_url_tree.mjs +25 -11
- package/esm2020/src/directives/router_link.mjs +6 -6
- package/esm2020/src/directives/router_link_active.mjs +22 -4
- package/esm2020/src/directives/router_outlet.mjs +25 -16
- package/esm2020/src/models.mjs +2 -7
- package/esm2020/src/operators/activate_routes.mjs +7 -14
- package/esm2020/src/operators/apply_redirects.mjs +3 -3
- package/esm2020/src/operators/resolve_data.mjs +5 -12
- package/esm2020/src/page_title_strategy.mjs +3 -3
- package/esm2020/src/recognize.mjs +24 -6
- package/esm2020/src/router.mjs +41 -25
- package/esm2020/src/router_config_loader.mjs +74 -27
- package/esm2020/src/router_module.mjs +10 -9
- package/esm2020/src/router_outlet_context.mjs +6 -1
- package/esm2020/src/router_preloader.mjs +48 -32
- package/esm2020/src/router_scroller.mjs +3 -3
- package/esm2020/src/router_state.mjs +3 -3
- package/esm2020/src/url_tree.mjs +1 -1
- package/esm2020/src/utils/config.mjs +71 -11
- package/esm2020/src/utils/config_matching.mjs +4 -1
- package/esm2020/src/utils/preactivation.mjs +5 -14
- package/esm2020/src/version.mjs +1 -1
- package/esm2020/testing/src/router_testing_module.mjs +4 -4
- package/fesm2015/router.mjs +844 -655
- package/fesm2015/router.mjs.map +1 -1
- package/fesm2015/testing.mjs +5 -5
- package/fesm2015/upgrade.mjs +1 -1
- package/fesm2020/router.mjs +831 -655
- package/fesm2020/router.mjs.map +1 -1
- package/fesm2020/testing.mjs +5 -5
- package/fesm2020/upgrade.mjs +1 -1
- package/{router.d.ts → index.d.ts} +3808 -3734
- package/package.json +8 -8
- package/testing/{testing.d.ts → index.d.ts} +65 -64
- package/upgrade/{upgrade.d.ts → index.d.ts} +51 -50
- package/testing/package.json +0 -9
- package/upgrade/package.json +0 -10
package/fesm2020/router.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular v14.0.0-next.
|
|
2
|
+
* @license Angular v14.0.0-next.15
|
|
3
3
|
* (c) 2010-2022 Google LLC. https://angular.io/
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
import * as i3 from '@angular/common';
|
|
8
8
|
import { Location, LocationStrategy, PlatformLocation, APP_BASE_HREF, ViewportScroller, HashLocationStrategy, PathLocationStrategy, LOCATION_INITIALIZED } from '@angular/common';
|
|
9
9
|
import * as i0 from '@angular/core';
|
|
10
|
-
import { ɵisObservable, ɵisPromise, EventEmitter, Directive, Attribute, Output, Component,
|
|
10
|
+
import { ɵisObservable, ɵisPromise, EventEmitter, Directive, Attribute, Output, Component, ɵisStandalone, ComponentFactoryResolver, createEnvironmentInjector, InjectionToken, InjectFlags, NgModuleFactory, Injectable, NgModuleRef, ɵConsole, NgZone, ɵcoerceToBoolean, Input, HostListener, HostBinding, Optional, ContentChildren, Injector, Compiler, NgProbeToken, ANALYZE_FOR_ENTRY_COMPONENTS, SkipSelf, Inject, APP_INITIALIZER, APP_BOOTSTRAP_LISTENER, NgModule, ApplicationRef, Version } from '@angular/core';
|
|
11
11
|
import { from, of, BehaviorSubject, combineLatest, throwError, EmptyError, concat, defer, Observable, EMPTY, ConnectableObservable, Subject } from 'rxjs';
|
|
12
|
-
import { map, switchMap, take, startWith, scan, filter, catchError, concatMap, last as last$1, first, mergeMap, tap, takeLast,
|
|
12
|
+
import { map, switchMap, take, startWith, scan, filter, catchError, concatMap, last as last$1, first, mergeMap, tap, takeLast, mapTo, finalize, refCount, defaultIfEmpty, mergeAll } from 'rxjs/operators';
|
|
13
13
|
import * as i1 from '@angular/platform-browser';
|
|
14
14
|
|
|
15
15
|
/**
|
|
@@ -1362,7 +1362,6 @@ class ActivatedRoute {
|
|
|
1362
1362
|
/** The outlet name of the route, a constant. */
|
|
1363
1363
|
outlet,
|
|
1364
1364
|
/** The component of the route, a constant. */
|
|
1365
|
-
// TODO(vsavkin): remove |string
|
|
1366
1365
|
component, futureSnapshot) {
|
|
1367
1366
|
this.url = url;
|
|
1368
1367
|
this.params = params;
|
|
@@ -1517,7 +1516,7 @@ class ActivatedRouteSnapshot {
|
|
|
1517
1516
|
/** The outlet name of the route */
|
|
1518
1517
|
outlet,
|
|
1519
1518
|
/** The component of the route */
|
|
1520
|
-
component, routeConfig, urlSegment, lastPathIndex, resolve) {
|
|
1519
|
+
component, routeConfig, urlSegment, lastPathIndex, resolve, correctedLastPathIndex) {
|
|
1521
1520
|
this.url = url;
|
|
1522
1521
|
this.params = params;
|
|
1523
1522
|
this.queryParams = queryParams;
|
|
@@ -1528,6 +1527,7 @@ class ActivatedRouteSnapshot {
|
|
|
1528
1527
|
this.routeConfig = routeConfig;
|
|
1529
1528
|
this._urlSegment = urlSegment;
|
|
1530
1529
|
this._lastPathIndex = lastPathIndex;
|
|
1530
|
+
this._correctedLastPathIndex = correctedLastPathIndex ?? lastPathIndex;
|
|
1531
1531
|
this._resolve = resolve;
|
|
1532
1532
|
}
|
|
1533
1533
|
/** The root of the router state */
|
|
@@ -1719,11 +1719,26 @@ function createUrlTree(route, urlTree, commands, queryParams, fragment) {
|
|
|
1719
1719
|
if (nav.toRoot()) {
|
|
1720
1720
|
return tree(urlTree.root, urlTree.root, new UrlSegmentGroup([], {}), queryParams, fragment);
|
|
1721
1721
|
}
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1722
|
+
function createTreeUsingPathIndex(lastPathIndex) {
|
|
1723
|
+
const startingPosition = findStartingPosition(nav, urlTree, route.snapshot?._urlSegment, lastPathIndex);
|
|
1724
|
+
const segmentGroup = startingPosition.processChildren ?
|
|
1725
|
+
updateSegmentGroupChildren(startingPosition.segmentGroup, startingPosition.index, nav.commands) :
|
|
1726
|
+
updateSegmentGroup(startingPosition.segmentGroup, startingPosition.index, nav.commands);
|
|
1727
|
+
return tree(urlTree.root, startingPosition.segmentGroup, segmentGroup, queryParams, fragment);
|
|
1728
|
+
}
|
|
1729
|
+
// Note: The types should disallow `snapshot` from being `undefined` but due to test mocks, this
|
|
1730
|
+
// may be the case. Since we try to access it at an earlier point before the refactor to add the
|
|
1731
|
+
// warning for `relativeLinkResolution: 'legacy'`, this may cause failures in tests where it
|
|
1732
|
+
// didn't before.
|
|
1733
|
+
const result = createTreeUsingPathIndex(route.snapshot?._lastPathIndex);
|
|
1734
|
+
// Check if application is relying on `relativeLinkResolution: 'legacy'`
|
|
1735
|
+
if (typeof ngDevMode === 'undefined' || !!ngDevMode) {
|
|
1736
|
+
const correctedResult = createTreeUsingPathIndex(route.snapshot?._correctedLastPathIndex);
|
|
1737
|
+
if (correctedResult.toString() !== result.toString()) {
|
|
1738
|
+
console.warn(`relativeLinkResolution: 'legacy' is deprecated and will be removed in a future version of Angular. The link to ${result.toString()} will change to ${correctedResult.toString()} if the code is not updated before then.`);
|
|
1739
|
+
}
|
|
1740
|
+
}
|
|
1741
|
+
return result;
|
|
1727
1742
|
}
|
|
1728
1743
|
function isMatrixParams(command) {
|
|
1729
1744
|
return typeof command === 'object' && command != null && !command.outlets && !command.segmentPath;
|
|
@@ -1828,12 +1843,11 @@ class Position {
|
|
|
1828
1843
|
this.index = index;
|
|
1829
1844
|
}
|
|
1830
1845
|
}
|
|
1831
|
-
function findStartingPosition(nav, tree,
|
|
1846
|
+
function findStartingPosition(nav, tree, segmentGroup, lastPathIndex) {
|
|
1832
1847
|
if (nav.isAbsolute) {
|
|
1833
1848
|
return new Position(tree.root, true, 0);
|
|
1834
1849
|
}
|
|
1835
|
-
if (
|
|
1836
|
-
const segmentGroup = route.snapshot._urlSegment;
|
|
1850
|
+
if (lastPathIndex === -1) {
|
|
1837
1851
|
// Pathless ActivatedRoute has _lastPathIndex === -1 but should not process children
|
|
1838
1852
|
// see issue #26224, #13011, #35687
|
|
1839
1853
|
// However, if the ActivatedRoute is the root we should process children like above.
|
|
@@ -1841,8 +1855,8 @@ function findStartingPosition(nav, tree, route) {
|
|
|
1841
1855
|
return new Position(segmentGroup, processChildren, 0);
|
|
1842
1856
|
}
|
|
1843
1857
|
const modifier = isMatrixParams(nav.commands[0]) ? 0 : 1;
|
|
1844
|
-
const index =
|
|
1845
|
-
return createPositionApplyingDoubleDots(
|
|
1858
|
+
const index = lastPathIndex + modifier;
|
|
1859
|
+
return createPositionApplyingDoubleDots(segmentGroup, index, nav.numberOfDoubleDots);
|
|
1846
1860
|
}
|
|
1847
1861
|
function createPositionApplyingDoubleDots(group, index, numberOfDoubleDots) {
|
|
1848
1862
|
let g = group;
|
|
@@ -2005,181 +2019,76 @@ function compare(path, params, segment) {
|
|
|
2005
2019
|
* Use of this source code is governed by an MIT-style license that can be
|
|
2006
2020
|
* found in the LICENSE file at https://angular.io/license
|
|
2007
2021
|
*/
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
class
|
|
2014
|
-
constructor(
|
|
2015
|
-
this.
|
|
2016
|
-
this.
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
this.
|
|
2024
|
-
|
|
2025
|
-
this.activateChildRoutes(futureRoot, currRoot, parentContexts);
|
|
2026
|
-
}
|
|
2027
|
-
// De-activate the child route that are not re-used for the future state
|
|
2028
|
-
deactivateChildRoutes(futureNode, currNode, contexts) {
|
|
2029
|
-
const children = nodeChildrenAsMap(currNode);
|
|
2030
|
-
// Recurse on the routes active in the future state to de-activate deeper children
|
|
2031
|
-
futureNode.children.forEach(futureChild => {
|
|
2032
|
-
const childOutletName = futureChild.value.outlet;
|
|
2033
|
-
this.deactivateRoutes(futureChild, children[childOutletName], contexts);
|
|
2034
|
-
delete children[childOutletName];
|
|
2035
|
-
});
|
|
2036
|
-
// De-activate the routes that will not be re-used
|
|
2037
|
-
forEach(children, (v, childName) => {
|
|
2038
|
-
this.deactivateRouteAndItsChildren(v, contexts);
|
|
2039
|
-
});
|
|
2040
|
-
}
|
|
2041
|
-
deactivateRoutes(futureNode, currNode, parentContext) {
|
|
2042
|
-
const future = futureNode.value;
|
|
2043
|
-
const curr = currNode ? currNode.value : null;
|
|
2044
|
-
if (future === curr) {
|
|
2045
|
-
// Reusing the node, check to see if the children need to be de-activated
|
|
2046
|
-
if (future.component) {
|
|
2047
|
-
// If we have a normal route, we need to go through an outlet.
|
|
2048
|
-
const context = parentContext.getContext(future.outlet);
|
|
2049
|
-
if (context) {
|
|
2050
|
-
this.deactivateChildRoutes(futureNode, currNode, context.children);
|
|
2051
|
-
}
|
|
2052
|
-
}
|
|
2053
|
-
else {
|
|
2054
|
-
// if we have a componentless route, we recurse but keep the same outlet map.
|
|
2055
|
-
this.deactivateChildRoutes(futureNode, currNode, parentContext);
|
|
2056
|
-
}
|
|
2057
|
-
}
|
|
2058
|
-
else {
|
|
2059
|
-
if (curr) {
|
|
2060
|
-
// Deactivate the current route which will not be re-used
|
|
2061
|
-
this.deactivateRouteAndItsChildren(currNode, parentContext);
|
|
2062
|
-
}
|
|
2063
|
-
}
|
|
2022
|
+
/**
|
|
2023
|
+
* Store contextual information about a `RouterOutlet`
|
|
2024
|
+
*
|
|
2025
|
+
* @publicApi
|
|
2026
|
+
*/
|
|
2027
|
+
class OutletContext {
|
|
2028
|
+
constructor() {
|
|
2029
|
+
this.outlet = null;
|
|
2030
|
+
this.route = null;
|
|
2031
|
+
/**
|
|
2032
|
+
* @deprecated Passing a resolver to retrieve a component factory is not required and is
|
|
2033
|
+
* deprecated since v14.
|
|
2034
|
+
*/
|
|
2035
|
+
this.resolver = null;
|
|
2036
|
+
this.injector = null;
|
|
2037
|
+
this.children = new ChildrenOutletContexts();
|
|
2038
|
+
this.attachRef = null;
|
|
2064
2039
|
}
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2040
|
+
}
|
|
2041
|
+
/**
|
|
2042
|
+
* Store contextual information about the children (= nested) `RouterOutlet`
|
|
2043
|
+
*
|
|
2044
|
+
* @publicApi
|
|
2045
|
+
*/
|
|
2046
|
+
class ChildrenOutletContexts {
|
|
2047
|
+
constructor() {
|
|
2048
|
+
// contexts for child outlets, by name.
|
|
2049
|
+
this.contexts = new Map();
|
|
2074
2050
|
}
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
const
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
this.deactivateRouteAndItsChildren(children[childOutlet], contexts);
|
|
2081
|
-
}
|
|
2082
|
-
if (context && context.outlet) {
|
|
2083
|
-
const componentRef = context.outlet.detach();
|
|
2084
|
-
const contexts = context.children.onOutletDeactivated();
|
|
2085
|
-
this.routeReuseStrategy.store(route.value.snapshot, { componentRef, route, contexts });
|
|
2086
|
-
}
|
|
2051
|
+
/** Called when a `RouterOutlet` directive is instantiated */
|
|
2052
|
+
onChildOutletCreated(childName, outlet) {
|
|
2053
|
+
const context = this.getOrCreateContext(childName);
|
|
2054
|
+
context.outlet = outlet;
|
|
2055
|
+
this.contexts.set(childName, context);
|
|
2087
2056
|
}
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
if (context && context.outlet) {
|
|
2098
|
-
// Destroy the component
|
|
2099
|
-
context.outlet.deactivate();
|
|
2100
|
-
// Destroy the contexts for all the outlets that were in the component
|
|
2101
|
-
context.children.onOutletDeactivated();
|
|
2102
|
-
// Clear the information about the attached component on the context but keep the reference to
|
|
2103
|
-
// the outlet.
|
|
2057
|
+
/**
|
|
2058
|
+
* Called when a `RouterOutlet` directive is destroyed.
|
|
2059
|
+
* We need to keep the context as the outlet could be destroyed inside a NgIf and might be
|
|
2060
|
+
* re-created later.
|
|
2061
|
+
*/
|
|
2062
|
+
onChildOutletDestroyed(childName) {
|
|
2063
|
+
const context = this.getContext(childName);
|
|
2064
|
+
if (context) {
|
|
2065
|
+
context.outlet = null;
|
|
2104
2066
|
context.attachRef = null;
|
|
2105
|
-
context.resolver = null;
|
|
2106
|
-
context.route = null;
|
|
2107
2067
|
}
|
|
2108
2068
|
}
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
}
|
|
2069
|
+
/**
|
|
2070
|
+
* Called when the corresponding route is deactivated during navigation.
|
|
2071
|
+
* Because the component get destroyed, all children outlet are destroyed.
|
|
2072
|
+
*/
|
|
2073
|
+
onOutletDeactivated() {
|
|
2074
|
+
const contexts = this.contexts;
|
|
2075
|
+
this.contexts = new Map();
|
|
2076
|
+
return contexts;
|
|
2118
2077
|
}
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
if (
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
const context = parentContexts.getOrCreateContext(future.outlet);
|
|
2128
|
-
this.activateChildRoutes(futureNode, currNode, context.children);
|
|
2129
|
-
}
|
|
2130
|
-
else {
|
|
2131
|
-
// if we have a componentless route, we recurse but keep the same outlet map.
|
|
2132
|
-
this.activateChildRoutes(futureNode, currNode, parentContexts);
|
|
2133
|
-
}
|
|
2134
|
-
}
|
|
2135
|
-
else {
|
|
2136
|
-
if (future.component) {
|
|
2137
|
-
// if we have a normal route, we need to place the component into the outlet and recurse.
|
|
2138
|
-
const context = parentContexts.getOrCreateContext(future.outlet);
|
|
2139
|
-
if (this.routeReuseStrategy.shouldAttach(future.snapshot)) {
|
|
2140
|
-
const stored = this.routeReuseStrategy.retrieve(future.snapshot);
|
|
2141
|
-
this.routeReuseStrategy.store(future.snapshot, null);
|
|
2142
|
-
context.children.onOutletReAttached(stored.contexts);
|
|
2143
|
-
context.attachRef = stored.componentRef;
|
|
2144
|
-
context.route = stored.route.value;
|
|
2145
|
-
if (context.outlet) {
|
|
2146
|
-
// Attach right away when the outlet has already been instantiated
|
|
2147
|
-
// Otherwise attach from `RouterOutlet.ngOnInit` when it is instantiated
|
|
2148
|
-
context.outlet.attach(stored.componentRef, stored.route.value);
|
|
2149
|
-
}
|
|
2150
|
-
advanceActivatedRoute(stored.route.value);
|
|
2151
|
-
this.activateChildRoutes(futureNode, null, context.children);
|
|
2152
|
-
}
|
|
2153
|
-
else {
|
|
2154
|
-
const config = parentLoadedConfig(future.snapshot);
|
|
2155
|
-
const cmpFactoryResolver = config ? config.module.componentFactoryResolver : null;
|
|
2156
|
-
context.attachRef = null;
|
|
2157
|
-
context.route = future;
|
|
2158
|
-
context.resolver = cmpFactoryResolver;
|
|
2159
|
-
if (context.outlet) {
|
|
2160
|
-
// Activate the outlet when it has already been instantiated
|
|
2161
|
-
// Otherwise it will get activated from its `ngOnInit` when instantiated
|
|
2162
|
-
context.outlet.activateWith(future, cmpFactoryResolver);
|
|
2163
|
-
}
|
|
2164
|
-
this.activateChildRoutes(futureNode, null, context.children);
|
|
2165
|
-
}
|
|
2166
|
-
}
|
|
2167
|
-
else {
|
|
2168
|
-
// if we have a componentless route, we recurse but keep the same outlet map.
|
|
2169
|
-
this.activateChildRoutes(futureNode, null, parentContexts);
|
|
2170
|
-
}
|
|
2078
|
+
onOutletReAttached(contexts) {
|
|
2079
|
+
this.contexts = contexts;
|
|
2080
|
+
}
|
|
2081
|
+
getOrCreateContext(childName) {
|
|
2082
|
+
let context = this.getContext(childName);
|
|
2083
|
+
if (!context) {
|
|
2084
|
+
context = new OutletContext();
|
|
2085
|
+
this.contexts.set(childName, context);
|
|
2171
2086
|
}
|
|
2087
|
+
return context;
|
|
2172
2088
|
}
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
for (let s = snapshot.parent; s; s = s.parent) {
|
|
2176
|
-
const route = s.routeConfig;
|
|
2177
|
-
if (route && route._loadedConfig)
|
|
2178
|
-
return route._loadedConfig;
|
|
2179
|
-
if (route && route.component)
|
|
2180
|
-
return null;
|
|
2089
|
+
getContext(childName) {
|
|
2090
|
+
return this.contexts.get(childName) || null;
|
|
2181
2091
|
}
|
|
2182
|
-
return null;
|
|
2183
2092
|
}
|
|
2184
2093
|
|
|
2185
2094
|
/**
|
|
@@ -2189,182 +2098,13 @@ function parentLoadedConfig(snapshot) {
|
|
|
2189
2098
|
* Use of this source code is governed by an MIT-style license that can be
|
|
2190
2099
|
* found in the LICENSE file at https://angular.io/license
|
|
2191
2100
|
*/
|
|
2192
|
-
class LoadedRouterConfig {
|
|
2193
|
-
constructor(routes, module) {
|
|
2194
|
-
this.routes = routes;
|
|
2195
|
-
this.module = module;
|
|
2196
|
-
}
|
|
2197
|
-
}
|
|
2198
|
-
|
|
2199
2101
|
/**
|
|
2200
|
-
* @
|
|
2201
|
-
* Copyright Google LLC All Rights Reserved.
|
|
2102
|
+
* @description
|
|
2202
2103
|
*
|
|
2203
|
-
*
|
|
2204
|
-
* found in the LICENSE file at https://angular.io/license
|
|
2205
|
-
*/
|
|
2206
|
-
/**
|
|
2207
|
-
* Simple function check, but generic so type inference will flow. Example:
|
|
2104
|
+
* Acts as a placeholder that Angular dynamically fills based on the current router state.
|
|
2208
2105
|
*
|
|
2209
|
-
*
|
|
2210
|
-
*
|
|
2211
|
-
* }
|
|
2212
|
-
*
|
|
2213
|
-
* if (isFunction<product>(fn)) {
|
|
2214
|
-
* return fn(1, 2);
|
|
2215
|
-
* } else {
|
|
2216
|
-
* throw "Must provide the `product` function";
|
|
2217
|
-
* }
|
|
2218
|
-
*/
|
|
2219
|
-
function isFunction(v) {
|
|
2220
|
-
return typeof v === 'function';
|
|
2221
|
-
}
|
|
2222
|
-
function isBoolean(v) {
|
|
2223
|
-
return typeof v === 'boolean';
|
|
2224
|
-
}
|
|
2225
|
-
function isUrlTree(v) {
|
|
2226
|
-
return v instanceof UrlTree;
|
|
2227
|
-
}
|
|
2228
|
-
function isCanLoad(guard) {
|
|
2229
|
-
return guard && isFunction(guard.canLoad);
|
|
2230
|
-
}
|
|
2231
|
-
function isCanActivate(guard) {
|
|
2232
|
-
return guard && isFunction(guard.canActivate);
|
|
2233
|
-
}
|
|
2234
|
-
function isCanActivateChild(guard) {
|
|
2235
|
-
return guard && isFunction(guard.canActivateChild);
|
|
2236
|
-
}
|
|
2237
|
-
function isCanDeactivate(guard) {
|
|
2238
|
-
return guard && isFunction(guard.canDeactivate);
|
|
2239
|
-
}
|
|
2240
|
-
|
|
2241
|
-
/**
|
|
2242
|
-
* @license
|
|
2243
|
-
* Copyright Google LLC All Rights Reserved.
|
|
2244
|
-
*
|
|
2245
|
-
* Use of this source code is governed by an MIT-style license that can be
|
|
2246
|
-
* found in the LICENSE file at https://angular.io/license
|
|
2247
|
-
*/
|
|
2248
|
-
const INITIAL_VALUE = Symbol('INITIAL_VALUE');
|
|
2249
|
-
function prioritizedGuardValue() {
|
|
2250
|
-
return switchMap(obs => {
|
|
2251
|
-
return combineLatest(obs.map(o => o.pipe(take(1), startWith(INITIAL_VALUE))))
|
|
2252
|
-
.pipe(scan((acc, list) => {
|
|
2253
|
-
let isPending = false;
|
|
2254
|
-
return list.reduce((innerAcc, val, i) => {
|
|
2255
|
-
if (innerAcc !== INITIAL_VALUE)
|
|
2256
|
-
return innerAcc;
|
|
2257
|
-
// Toggle pending flag if any values haven't been set yet
|
|
2258
|
-
if (val === INITIAL_VALUE)
|
|
2259
|
-
isPending = true;
|
|
2260
|
-
// Any other return values are only valid if we haven't yet hit a pending
|
|
2261
|
-
// call. This guarantees that in the case of a guard at the bottom of the
|
|
2262
|
-
// tree that returns a redirect, we will wait for the higher priority
|
|
2263
|
-
// guard at the top to finish before performing the redirect.
|
|
2264
|
-
if (!isPending) {
|
|
2265
|
-
// Early return when we hit a `false` value as that should always
|
|
2266
|
-
// cancel navigation
|
|
2267
|
-
if (val === false)
|
|
2268
|
-
return val;
|
|
2269
|
-
if (i === list.length - 1 || isUrlTree(val)) {
|
|
2270
|
-
return val;
|
|
2271
|
-
}
|
|
2272
|
-
}
|
|
2273
|
-
return innerAcc;
|
|
2274
|
-
}, acc);
|
|
2275
|
-
}, INITIAL_VALUE), filter(item => item !== INITIAL_VALUE), map(item => isUrlTree(item) ? item : item === true), //
|
|
2276
|
-
take(1));
|
|
2277
|
-
});
|
|
2278
|
-
}
|
|
2279
|
-
|
|
2280
|
-
/**
|
|
2281
|
-
* @license
|
|
2282
|
-
* Copyright Google LLC All Rights Reserved.
|
|
2283
|
-
*
|
|
2284
|
-
* Use of this source code is governed by an MIT-style license that can be
|
|
2285
|
-
* found in the LICENSE file at https://angular.io/license
|
|
2286
|
-
*/
|
|
2287
|
-
/**
|
|
2288
|
-
* Store contextual information about a `RouterOutlet`
|
|
2289
|
-
*
|
|
2290
|
-
* @publicApi
|
|
2291
|
-
*/
|
|
2292
|
-
class OutletContext {
|
|
2293
|
-
constructor() {
|
|
2294
|
-
this.outlet = null;
|
|
2295
|
-
this.route = null;
|
|
2296
|
-
this.resolver = null;
|
|
2297
|
-
this.children = new ChildrenOutletContexts();
|
|
2298
|
-
this.attachRef = null;
|
|
2299
|
-
}
|
|
2300
|
-
}
|
|
2301
|
-
/**
|
|
2302
|
-
* Store contextual information about the children (= nested) `RouterOutlet`
|
|
2303
|
-
*
|
|
2304
|
-
* @publicApi
|
|
2305
|
-
*/
|
|
2306
|
-
class ChildrenOutletContexts {
|
|
2307
|
-
constructor() {
|
|
2308
|
-
// contexts for child outlets, by name.
|
|
2309
|
-
this.contexts = new Map();
|
|
2310
|
-
}
|
|
2311
|
-
/** Called when a `RouterOutlet` directive is instantiated */
|
|
2312
|
-
onChildOutletCreated(childName, outlet) {
|
|
2313
|
-
const context = this.getOrCreateContext(childName);
|
|
2314
|
-
context.outlet = outlet;
|
|
2315
|
-
this.contexts.set(childName, context);
|
|
2316
|
-
}
|
|
2317
|
-
/**
|
|
2318
|
-
* Called when a `RouterOutlet` directive is destroyed.
|
|
2319
|
-
* We need to keep the context as the outlet could be destroyed inside a NgIf and might be
|
|
2320
|
-
* re-created later.
|
|
2321
|
-
*/
|
|
2322
|
-
onChildOutletDestroyed(childName) {
|
|
2323
|
-
const context = this.getContext(childName);
|
|
2324
|
-
if (context) {
|
|
2325
|
-
context.outlet = null;
|
|
2326
|
-
context.attachRef = null;
|
|
2327
|
-
}
|
|
2328
|
-
}
|
|
2329
|
-
/**
|
|
2330
|
-
* Called when the corresponding route is deactivated during navigation.
|
|
2331
|
-
* Because the component get destroyed, all children outlet are destroyed.
|
|
2332
|
-
*/
|
|
2333
|
-
onOutletDeactivated() {
|
|
2334
|
-
const contexts = this.contexts;
|
|
2335
|
-
this.contexts = new Map();
|
|
2336
|
-
return contexts;
|
|
2337
|
-
}
|
|
2338
|
-
onOutletReAttached(contexts) {
|
|
2339
|
-
this.contexts = contexts;
|
|
2340
|
-
}
|
|
2341
|
-
getOrCreateContext(childName) {
|
|
2342
|
-
let context = this.getContext(childName);
|
|
2343
|
-
if (!context) {
|
|
2344
|
-
context = new OutletContext();
|
|
2345
|
-
this.contexts.set(childName, context);
|
|
2346
|
-
}
|
|
2347
|
-
return context;
|
|
2348
|
-
}
|
|
2349
|
-
getContext(childName) {
|
|
2350
|
-
return this.contexts.get(childName) || null;
|
|
2351
|
-
}
|
|
2352
|
-
}
|
|
2353
|
-
|
|
2354
|
-
/**
|
|
2355
|
-
* @license
|
|
2356
|
-
* Copyright Google LLC All Rights Reserved.
|
|
2357
|
-
*
|
|
2358
|
-
* Use of this source code is governed by an MIT-style license that can be
|
|
2359
|
-
* found in the LICENSE file at https://angular.io/license
|
|
2360
|
-
*/
|
|
2361
|
-
/**
|
|
2362
|
-
* @description
|
|
2363
|
-
*
|
|
2364
|
-
* Acts as a placeholder that Angular dynamically fills based on the current router state.
|
|
2365
|
-
*
|
|
2366
|
-
* Each outlet can have a unique name, determined by the optional `name` attribute.
|
|
2367
|
-
* The name cannot be set or changed dynamically. If not set, default value is "primary".
|
|
2106
|
+
* Each outlet can have a unique name, determined by the optional `name` attribute.
|
|
2107
|
+
* The name cannot be set or changed dynamically. If not set, default value is "primary".
|
|
2368
2108
|
*
|
|
2369
2109
|
* ```
|
|
2370
2110
|
* <router-outlet></router-outlet>
|
|
@@ -2410,11 +2150,11 @@ class ChildrenOutletContexts {
|
|
|
2410
2150
|
* @publicApi
|
|
2411
2151
|
*/
|
|
2412
2152
|
class RouterOutlet {
|
|
2413
|
-
constructor(parentContexts, location,
|
|
2153
|
+
constructor(parentContexts, location, name, changeDetector, environmentInjector) {
|
|
2414
2154
|
this.parentContexts = parentContexts;
|
|
2415
2155
|
this.location = location;
|
|
2416
|
-
this.resolver = resolver;
|
|
2417
2156
|
this.changeDetector = changeDetector;
|
|
2157
|
+
this.environmentInjector = environmentInjector;
|
|
2418
2158
|
this.activated = null;
|
|
2419
2159
|
this._activatedRoute = null;
|
|
2420
2160
|
this.activateEvents = new EventEmitter();
|
|
@@ -2449,7 +2189,7 @@ class RouterOutlet {
|
|
|
2449
2189
|
}
|
|
2450
2190
|
else {
|
|
2451
2191
|
// otherwise the component defined in the configuration is created
|
|
2452
|
-
this.activateWith(context.route, context.
|
|
2192
|
+
this.activateWith(context.route, context.injector);
|
|
2453
2193
|
}
|
|
2454
2194
|
}
|
|
2455
2195
|
}
|
|
@@ -2508,33 +2248,39 @@ class RouterOutlet {
|
|
|
2508
2248
|
this.deactivateEvents.emit(c);
|
|
2509
2249
|
}
|
|
2510
2250
|
}
|
|
2511
|
-
activateWith(activatedRoute,
|
|
2251
|
+
activateWith(activatedRoute, resolverOrInjector) {
|
|
2512
2252
|
if (this.isActivated) {
|
|
2513
2253
|
throw new Error('Cannot activate an already activated outlet');
|
|
2514
2254
|
}
|
|
2515
2255
|
this._activatedRoute = activatedRoute;
|
|
2256
|
+
const location = this.location;
|
|
2516
2257
|
const snapshot = activatedRoute._futureSnapshot;
|
|
2517
|
-
const component = snapshot.
|
|
2518
|
-
resolver = resolver || this.resolver;
|
|
2519
|
-
const factory = resolver.resolveComponentFactory(component);
|
|
2258
|
+
const component = snapshot.component;
|
|
2520
2259
|
const childContexts = this.parentContexts.getOrCreateContext(this.name).children;
|
|
2521
|
-
const injector = new OutletInjector(activatedRoute, childContexts,
|
|
2522
|
-
|
|
2260
|
+
const injector = new OutletInjector(activatedRoute, childContexts, location.injector);
|
|
2261
|
+
if (resolverOrInjector && isComponentFactoryResolver(resolverOrInjector)) {
|
|
2262
|
+
const factory = resolverOrInjector.resolveComponentFactory(component);
|
|
2263
|
+
this.activated = location.createComponent(factory, location.length, injector);
|
|
2264
|
+
}
|
|
2265
|
+
else {
|
|
2266
|
+
const environmentInjector = resolverOrInjector ?? this.environmentInjector;
|
|
2267
|
+
this.activated = location.createComponent(component, { index: location.length, injector, environmentInjector });
|
|
2268
|
+
}
|
|
2523
2269
|
// Calling `markForCheck` to make sure we will run the change detection when the
|
|
2524
2270
|
// `RouterOutlet` is inside a `ChangeDetectionStrategy.OnPush` component.
|
|
2525
2271
|
this.changeDetector.markForCheck();
|
|
2526
2272
|
this.activateEvents.emit(this.activated.instance);
|
|
2527
2273
|
}
|
|
2528
2274
|
}
|
|
2529
|
-
RouterOutlet.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
2530
|
-
RouterOutlet.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
2531
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
2275
|
+
RouterOutlet.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: RouterOutlet, deps: [{ token: ChildrenOutletContexts }, { token: i0.ViewContainerRef }, { token: 'name', attribute: true }, { token: i0.ChangeDetectorRef }, { token: i0.EnvironmentInjector }], target: i0.ɵɵFactoryTarget.Directive });
|
|
2276
|
+
RouterOutlet.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.15", type: RouterOutlet, selector: "router-outlet", outputs: { activateEvents: "activate", deactivateEvents: "deactivate", attachEvents: "attach", detachEvents: "detach" }, exportAs: ["outlet"], ngImport: i0 });
|
|
2277
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: RouterOutlet, decorators: [{
|
|
2532
2278
|
type: Directive,
|
|
2533
2279
|
args: [{ selector: 'router-outlet', exportAs: 'outlet' }]
|
|
2534
|
-
}], ctorParameters: function () { return [{ type: ChildrenOutletContexts }, { type: i0.ViewContainerRef }, { type:
|
|
2280
|
+
}], ctorParameters: function () { return [{ type: ChildrenOutletContexts }, { type: i0.ViewContainerRef }, { type: undefined, decorators: [{
|
|
2535
2281
|
type: Attribute,
|
|
2536
2282
|
args: ['name']
|
|
2537
|
-
}] }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { activateEvents: [{
|
|
2283
|
+
}] }, { type: i0.ChangeDetectorRef }, { type: i0.EnvironmentInjector }]; }, propDecorators: { activateEvents: [{
|
|
2538
2284
|
type: Output,
|
|
2539
2285
|
args: ['activate']
|
|
2540
2286
|
}], deactivateEvents: [{
|
|
@@ -2560,7 +2306,385 @@ class OutletInjector {
|
|
|
2560
2306
|
if (token === ChildrenOutletContexts) {
|
|
2561
2307
|
return this.childContexts;
|
|
2562
2308
|
}
|
|
2563
|
-
return this.parent.get(token, notFoundValue);
|
|
2309
|
+
return this.parent.get(token, notFoundValue);
|
|
2310
|
+
}
|
|
2311
|
+
}
|
|
2312
|
+
function isComponentFactoryResolver(item) {
|
|
2313
|
+
return !!item.resolveComponentFactory;
|
|
2314
|
+
}
|
|
2315
|
+
|
|
2316
|
+
/**
|
|
2317
|
+
* @license
|
|
2318
|
+
* Copyright Google LLC All Rights Reserved.
|
|
2319
|
+
*
|
|
2320
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
2321
|
+
* found in the LICENSE file at https://angular.io/license
|
|
2322
|
+
*/
|
|
2323
|
+
/**
|
|
2324
|
+
* This component is used internally within the router to be a placeholder when an empty
|
|
2325
|
+
* router-outlet is needed. For example, with a config such as:
|
|
2326
|
+
*
|
|
2327
|
+
* `{path: 'parent', outlet: 'nav', children: [...]}`
|
|
2328
|
+
*
|
|
2329
|
+
* In order to render, there needs to be a component on this config, which will default
|
|
2330
|
+
* to this `EmptyOutletComponent`.
|
|
2331
|
+
*/
|
|
2332
|
+
class ɵEmptyOutletComponent {
|
|
2333
|
+
}
|
|
2334
|
+
ɵEmptyOutletComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: ɵEmptyOutletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2335
|
+
ɵEmptyOutletComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "14.0.0-next.15", type: ɵEmptyOutletComponent, selector: "ng-component", ngImport: i0, template: `<router-outlet></router-outlet>`, isInline: true, dependencies: [{ kind: "directive", type: RouterOutlet, selector: "router-outlet", outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }] });
|
|
2336
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: ɵEmptyOutletComponent, decorators: [{
|
|
2337
|
+
type: Component,
|
|
2338
|
+
args: [{ template: `<router-outlet></router-outlet>` }]
|
|
2339
|
+
}] });
|
|
2340
|
+
|
|
2341
|
+
/**
|
|
2342
|
+
* @license
|
|
2343
|
+
* Copyright Google LLC All Rights Reserved.
|
|
2344
|
+
*
|
|
2345
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
2346
|
+
* found in the LICENSE file at https://angular.io/license
|
|
2347
|
+
*/
|
|
2348
|
+
function getLoadedRoutes(route) {
|
|
2349
|
+
return route._loadedRoutes;
|
|
2350
|
+
}
|
|
2351
|
+
function getLoadedInjector(route) {
|
|
2352
|
+
return route._loadedInjector;
|
|
2353
|
+
}
|
|
2354
|
+
function getLoadedComponent(route) {
|
|
2355
|
+
return route._loadedComponent;
|
|
2356
|
+
}
|
|
2357
|
+
function getProvidersInjector(route) {
|
|
2358
|
+
return route._injector;
|
|
2359
|
+
}
|
|
2360
|
+
function validateConfig(config, parentPath = '', requireStandaloneComponents = false) {
|
|
2361
|
+
// forEach doesn't iterate undefined values
|
|
2362
|
+
for (let i = 0; i < config.length; i++) {
|
|
2363
|
+
const route = config[i];
|
|
2364
|
+
const fullPath = getFullPath(parentPath, route);
|
|
2365
|
+
validateNode(route, fullPath, requireStandaloneComponents);
|
|
2366
|
+
}
|
|
2367
|
+
}
|
|
2368
|
+
function assertStandalone(fullPath, component) {
|
|
2369
|
+
if (component && !ɵisStandalone(component)) {
|
|
2370
|
+
throw new Error(`Invalid configuration of route '${fullPath}'. The component must be standalone.`);
|
|
2371
|
+
}
|
|
2372
|
+
}
|
|
2373
|
+
function validateNode(route, fullPath, requireStandaloneComponents) {
|
|
2374
|
+
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
2375
|
+
if (!route) {
|
|
2376
|
+
throw new Error(`
|
|
2377
|
+
Invalid configuration of route '${fullPath}': Encountered undefined route.
|
|
2378
|
+
The reason might be an extra comma.
|
|
2379
|
+
|
|
2380
|
+
Example:
|
|
2381
|
+
const routes: Routes = [
|
|
2382
|
+
{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },
|
|
2383
|
+
{ path: 'dashboard', component: DashboardComponent },, << two commas
|
|
2384
|
+
{ path: 'detail/:id', component: HeroDetailComponent }
|
|
2385
|
+
];
|
|
2386
|
+
`);
|
|
2387
|
+
}
|
|
2388
|
+
if (Array.isArray(route)) {
|
|
2389
|
+
throw new Error(`Invalid configuration of route '${fullPath}': Array cannot be specified`);
|
|
2390
|
+
}
|
|
2391
|
+
if (!route.component && !route.loadComponent && !route.children && !route.loadChildren &&
|
|
2392
|
+
(route.outlet && route.outlet !== PRIMARY_OUTLET)) {
|
|
2393
|
+
throw new Error(`Invalid configuration of route '${fullPath}': a componentless route without children or loadChildren cannot have a named outlet set`);
|
|
2394
|
+
}
|
|
2395
|
+
if (route.redirectTo && route.children) {
|
|
2396
|
+
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and children cannot be used together`);
|
|
2397
|
+
}
|
|
2398
|
+
if (route.redirectTo && route.loadChildren) {
|
|
2399
|
+
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and loadChildren cannot be used together`);
|
|
2400
|
+
}
|
|
2401
|
+
if (route.children && route.loadChildren) {
|
|
2402
|
+
throw new Error(`Invalid configuration of route '${fullPath}': children and loadChildren cannot be used together`);
|
|
2403
|
+
}
|
|
2404
|
+
if (route.redirectTo && (route.component || route.loadComponent)) {
|
|
2405
|
+
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and component/loadComponent cannot be used together`);
|
|
2406
|
+
}
|
|
2407
|
+
if (route.component && route.loadComponent) {
|
|
2408
|
+
throw new Error(`Invalid configuration of route '${fullPath}': component and loadComponent cannot be used together`);
|
|
2409
|
+
}
|
|
2410
|
+
if (route.redirectTo && route.canActivate) {
|
|
2411
|
+
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and canActivate cannot be used together. Redirects happen before activation ` +
|
|
2412
|
+
`so canActivate will never be executed.`);
|
|
2413
|
+
}
|
|
2414
|
+
if (route.path && route.matcher) {
|
|
2415
|
+
throw new Error(`Invalid configuration of route '${fullPath}': path and matcher cannot be used together`);
|
|
2416
|
+
}
|
|
2417
|
+
if (route.redirectTo === void 0 && !route.component && !route.loadComponent &&
|
|
2418
|
+
!route.children && !route.loadChildren) {
|
|
2419
|
+
throw new Error(`Invalid configuration of route '${fullPath}'. One of the following must be provided: component, loadComponent, redirectTo, children or loadChildren`);
|
|
2420
|
+
}
|
|
2421
|
+
if (route.path === void 0 && route.matcher === void 0) {
|
|
2422
|
+
throw new Error(`Invalid configuration of route '${fullPath}': routes must have either a path or a matcher specified`);
|
|
2423
|
+
}
|
|
2424
|
+
if (typeof route.path === 'string' && route.path.charAt(0) === '/') {
|
|
2425
|
+
throw new Error(`Invalid configuration of route '${fullPath}': path cannot start with a slash`);
|
|
2426
|
+
}
|
|
2427
|
+
if (route.path === '' && route.redirectTo !== void 0 && route.pathMatch === void 0) {
|
|
2428
|
+
const exp = `The default value of 'pathMatch' is 'prefix', but often the intent is to use 'full'.`;
|
|
2429
|
+
throw new Error(`Invalid configuration of route '{path: "${fullPath}", redirectTo: "${route.redirectTo}"}': please provide 'pathMatch'. ${exp}`);
|
|
2430
|
+
}
|
|
2431
|
+
if (requireStandaloneComponents) {
|
|
2432
|
+
assertStandalone(fullPath, route.component);
|
|
2433
|
+
}
|
|
2434
|
+
}
|
|
2435
|
+
if (route.children) {
|
|
2436
|
+
validateConfig(route.children, fullPath, requireStandaloneComponents);
|
|
2437
|
+
}
|
|
2438
|
+
}
|
|
2439
|
+
function getFullPath(parentPath, currentRoute) {
|
|
2440
|
+
if (!currentRoute) {
|
|
2441
|
+
return parentPath;
|
|
2442
|
+
}
|
|
2443
|
+
if (!parentPath && !currentRoute.path) {
|
|
2444
|
+
return '';
|
|
2445
|
+
}
|
|
2446
|
+
else if (parentPath && !currentRoute.path) {
|
|
2447
|
+
return `${parentPath}/`;
|
|
2448
|
+
}
|
|
2449
|
+
else if (!parentPath && currentRoute.path) {
|
|
2450
|
+
return currentRoute.path;
|
|
2451
|
+
}
|
|
2452
|
+
else {
|
|
2453
|
+
return `${parentPath}/${currentRoute.path}`;
|
|
2454
|
+
}
|
|
2455
|
+
}
|
|
2456
|
+
/**
|
|
2457
|
+
* Makes a copy of the config and adds any default required properties.
|
|
2458
|
+
*/
|
|
2459
|
+
function standardizeConfig(r) {
|
|
2460
|
+
const children = r.children && r.children.map(standardizeConfig);
|
|
2461
|
+
const c = children ? { ...r, children } : { ...r };
|
|
2462
|
+
if ((!c.component && !c.loadComponent) && (children || c.loadChildren) &&
|
|
2463
|
+
(c.outlet && c.outlet !== PRIMARY_OUTLET)) {
|
|
2464
|
+
c.component = ɵEmptyOutletComponent;
|
|
2465
|
+
}
|
|
2466
|
+
return c;
|
|
2467
|
+
}
|
|
2468
|
+
/** Returns the `route.outlet` or PRIMARY_OUTLET if none exists. */
|
|
2469
|
+
function getOutlet(route) {
|
|
2470
|
+
return route.outlet || PRIMARY_OUTLET;
|
|
2471
|
+
}
|
|
2472
|
+
/**
|
|
2473
|
+
* Sorts the `routes` such that the ones with an outlet matching `outletName` come first.
|
|
2474
|
+
* The order of the configs is otherwise preserved.
|
|
2475
|
+
*/
|
|
2476
|
+
function sortByMatchingOutlets(routes, outletName) {
|
|
2477
|
+
const sortedConfig = routes.filter(r => getOutlet(r) === outletName);
|
|
2478
|
+
sortedConfig.push(...routes.filter(r => getOutlet(r) !== outletName));
|
|
2479
|
+
return sortedConfig;
|
|
2480
|
+
}
|
|
2481
|
+
/**
|
|
2482
|
+
* Gets the first injector in the snapshot's parent tree.
|
|
2483
|
+
*
|
|
2484
|
+
* If the `Route` has a static list of providers, the returned injector will be the one created from
|
|
2485
|
+
* those. If it does not exist, the returned injector may come from the parents, which may be from a
|
|
2486
|
+
* loaded config or their static providers.
|
|
2487
|
+
*
|
|
2488
|
+
* Returns `null` if there is neither this nor any parents have a stored injector.
|
|
2489
|
+
*
|
|
2490
|
+
* Generally used for retrieving the injector to use for getting tokens for guards/resolvers and
|
|
2491
|
+
* also used for getting the correct injector to use for creating components.
|
|
2492
|
+
*/
|
|
2493
|
+
function getClosestRouteInjector(snapshot) {
|
|
2494
|
+
if (!snapshot)
|
|
2495
|
+
return null;
|
|
2496
|
+
// If the current route has its own injector, which is created from the static providers on the
|
|
2497
|
+
// route itself, we should use that. Otherwise, we start at the parent since we do not want to
|
|
2498
|
+
// include the lazy loaded injector from this route.
|
|
2499
|
+
if (snapshot.routeConfig?._injector) {
|
|
2500
|
+
return snapshot.routeConfig._injector;
|
|
2501
|
+
}
|
|
2502
|
+
for (let s = snapshot.parent; s; s = s.parent) {
|
|
2503
|
+
const route = s.routeConfig;
|
|
2504
|
+
// Note that the order here is important. `_loadedInjector` stored on the route with
|
|
2505
|
+
// `loadChildren: () => NgModule` so it applies to child routes with priority. The `_injector`
|
|
2506
|
+
// is created from the static providers on that parent route, so it applies to the children as
|
|
2507
|
+
// well, but only if there is no lazy loaded NgModuleRef injector.
|
|
2508
|
+
if (route?._loadedInjector)
|
|
2509
|
+
return route._loadedInjector;
|
|
2510
|
+
if (route?._injector)
|
|
2511
|
+
return route._injector;
|
|
2512
|
+
}
|
|
2513
|
+
return null;
|
|
2514
|
+
}
|
|
2515
|
+
|
|
2516
|
+
/**
|
|
2517
|
+
* @license
|
|
2518
|
+
* Copyright Google LLC All Rights Reserved.
|
|
2519
|
+
*
|
|
2520
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
2521
|
+
* found in the LICENSE file at https://angular.io/license
|
|
2522
|
+
*/
|
|
2523
|
+
const activateRoutes = (rootContexts, routeReuseStrategy, forwardEvent) => map(t => {
|
|
2524
|
+
new ActivateRoutes(routeReuseStrategy, t.targetRouterState, t.currentRouterState, forwardEvent)
|
|
2525
|
+
.activate(rootContexts);
|
|
2526
|
+
return t;
|
|
2527
|
+
});
|
|
2528
|
+
class ActivateRoutes {
|
|
2529
|
+
constructor(routeReuseStrategy, futureState, currState, forwardEvent) {
|
|
2530
|
+
this.routeReuseStrategy = routeReuseStrategy;
|
|
2531
|
+
this.futureState = futureState;
|
|
2532
|
+
this.currState = currState;
|
|
2533
|
+
this.forwardEvent = forwardEvent;
|
|
2534
|
+
}
|
|
2535
|
+
activate(parentContexts) {
|
|
2536
|
+
const futureRoot = this.futureState._root;
|
|
2537
|
+
const currRoot = this.currState ? this.currState._root : null;
|
|
2538
|
+
this.deactivateChildRoutes(futureRoot, currRoot, parentContexts);
|
|
2539
|
+
advanceActivatedRoute(this.futureState.root);
|
|
2540
|
+
this.activateChildRoutes(futureRoot, currRoot, parentContexts);
|
|
2541
|
+
}
|
|
2542
|
+
// De-activate the child route that are not re-used for the future state
|
|
2543
|
+
deactivateChildRoutes(futureNode, currNode, contexts) {
|
|
2544
|
+
const children = nodeChildrenAsMap(currNode);
|
|
2545
|
+
// Recurse on the routes active in the future state to de-activate deeper children
|
|
2546
|
+
futureNode.children.forEach(futureChild => {
|
|
2547
|
+
const childOutletName = futureChild.value.outlet;
|
|
2548
|
+
this.deactivateRoutes(futureChild, children[childOutletName], contexts);
|
|
2549
|
+
delete children[childOutletName];
|
|
2550
|
+
});
|
|
2551
|
+
// De-activate the routes that will not be re-used
|
|
2552
|
+
forEach(children, (v, childName) => {
|
|
2553
|
+
this.deactivateRouteAndItsChildren(v, contexts);
|
|
2554
|
+
});
|
|
2555
|
+
}
|
|
2556
|
+
deactivateRoutes(futureNode, currNode, parentContext) {
|
|
2557
|
+
const future = futureNode.value;
|
|
2558
|
+
const curr = currNode ? currNode.value : null;
|
|
2559
|
+
if (future === curr) {
|
|
2560
|
+
// Reusing the node, check to see if the children need to be de-activated
|
|
2561
|
+
if (future.component) {
|
|
2562
|
+
// If we have a normal route, we need to go through an outlet.
|
|
2563
|
+
const context = parentContext.getContext(future.outlet);
|
|
2564
|
+
if (context) {
|
|
2565
|
+
this.deactivateChildRoutes(futureNode, currNode, context.children);
|
|
2566
|
+
}
|
|
2567
|
+
}
|
|
2568
|
+
else {
|
|
2569
|
+
// if we have a componentless route, we recurse but keep the same outlet map.
|
|
2570
|
+
this.deactivateChildRoutes(futureNode, currNode, parentContext);
|
|
2571
|
+
}
|
|
2572
|
+
}
|
|
2573
|
+
else {
|
|
2574
|
+
if (curr) {
|
|
2575
|
+
// Deactivate the current route which will not be re-used
|
|
2576
|
+
this.deactivateRouteAndItsChildren(currNode, parentContext);
|
|
2577
|
+
}
|
|
2578
|
+
}
|
|
2579
|
+
}
|
|
2580
|
+
deactivateRouteAndItsChildren(route, parentContexts) {
|
|
2581
|
+
// If there is no component, the Route is never attached to an outlet (because there is no
|
|
2582
|
+
// component to attach).
|
|
2583
|
+
if (route.value.component && this.routeReuseStrategy.shouldDetach(route.value.snapshot)) {
|
|
2584
|
+
this.detachAndStoreRouteSubtree(route, parentContexts);
|
|
2585
|
+
}
|
|
2586
|
+
else {
|
|
2587
|
+
this.deactivateRouteAndOutlet(route, parentContexts);
|
|
2588
|
+
}
|
|
2589
|
+
}
|
|
2590
|
+
detachAndStoreRouteSubtree(route, parentContexts) {
|
|
2591
|
+
const context = parentContexts.getContext(route.value.outlet);
|
|
2592
|
+
const contexts = context && route.value.component ? context.children : parentContexts;
|
|
2593
|
+
const children = nodeChildrenAsMap(route);
|
|
2594
|
+
for (const childOutlet of Object.keys(children)) {
|
|
2595
|
+
this.deactivateRouteAndItsChildren(children[childOutlet], contexts);
|
|
2596
|
+
}
|
|
2597
|
+
if (context && context.outlet) {
|
|
2598
|
+
const componentRef = context.outlet.detach();
|
|
2599
|
+
const contexts = context.children.onOutletDeactivated();
|
|
2600
|
+
this.routeReuseStrategy.store(route.value.snapshot, { componentRef, route, contexts });
|
|
2601
|
+
}
|
|
2602
|
+
}
|
|
2603
|
+
deactivateRouteAndOutlet(route, parentContexts) {
|
|
2604
|
+
const context = parentContexts.getContext(route.value.outlet);
|
|
2605
|
+
// The context could be `null` if we are on a componentless route but there may still be
|
|
2606
|
+
// children that need deactivating.
|
|
2607
|
+
const contexts = context && route.value.component ? context.children : parentContexts;
|
|
2608
|
+
const children = nodeChildrenAsMap(route);
|
|
2609
|
+
for (const childOutlet of Object.keys(children)) {
|
|
2610
|
+
this.deactivateRouteAndItsChildren(children[childOutlet], contexts);
|
|
2611
|
+
}
|
|
2612
|
+
if (context && context.outlet) {
|
|
2613
|
+
// Destroy the component
|
|
2614
|
+
context.outlet.deactivate();
|
|
2615
|
+
// Destroy the contexts for all the outlets that were in the component
|
|
2616
|
+
context.children.onOutletDeactivated();
|
|
2617
|
+
// Clear the information about the attached component on the context but keep the reference to
|
|
2618
|
+
// the outlet.
|
|
2619
|
+
context.attachRef = null;
|
|
2620
|
+
context.resolver = null;
|
|
2621
|
+
context.route = null;
|
|
2622
|
+
}
|
|
2623
|
+
}
|
|
2624
|
+
activateChildRoutes(futureNode, currNode, contexts) {
|
|
2625
|
+
const children = nodeChildrenAsMap(currNode);
|
|
2626
|
+
futureNode.children.forEach(c => {
|
|
2627
|
+
this.activateRoutes(c, children[c.value.outlet], contexts);
|
|
2628
|
+
this.forwardEvent(new ActivationEnd(c.value.snapshot));
|
|
2629
|
+
});
|
|
2630
|
+
if (futureNode.children.length) {
|
|
2631
|
+
this.forwardEvent(new ChildActivationEnd(futureNode.value.snapshot));
|
|
2632
|
+
}
|
|
2633
|
+
}
|
|
2634
|
+
activateRoutes(futureNode, currNode, parentContexts) {
|
|
2635
|
+
const future = futureNode.value;
|
|
2636
|
+
const curr = currNode ? currNode.value : null;
|
|
2637
|
+
advanceActivatedRoute(future);
|
|
2638
|
+
// reusing the node
|
|
2639
|
+
if (future === curr) {
|
|
2640
|
+
if (future.component) {
|
|
2641
|
+
// If we have a normal route, we need to go through an outlet.
|
|
2642
|
+
const context = parentContexts.getOrCreateContext(future.outlet);
|
|
2643
|
+
this.activateChildRoutes(futureNode, currNode, context.children);
|
|
2644
|
+
}
|
|
2645
|
+
else {
|
|
2646
|
+
// if we have a componentless route, we recurse but keep the same outlet map.
|
|
2647
|
+
this.activateChildRoutes(futureNode, currNode, parentContexts);
|
|
2648
|
+
}
|
|
2649
|
+
}
|
|
2650
|
+
else {
|
|
2651
|
+
if (future.component) {
|
|
2652
|
+
// if we have a normal route, we need to place the component into the outlet and recurse.
|
|
2653
|
+
const context = parentContexts.getOrCreateContext(future.outlet);
|
|
2654
|
+
if (this.routeReuseStrategy.shouldAttach(future.snapshot)) {
|
|
2655
|
+
const stored = this.routeReuseStrategy.retrieve(future.snapshot);
|
|
2656
|
+
this.routeReuseStrategy.store(future.snapshot, null);
|
|
2657
|
+
context.children.onOutletReAttached(stored.contexts);
|
|
2658
|
+
context.attachRef = stored.componentRef;
|
|
2659
|
+
context.route = stored.route.value;
|
|
2660
|
+
if (context.outlet) {
|
|
2661
|
+
// Attach right away when the outlet has already been instantiated
|
|
2662
|
+
// Otherwise attach from `RouterOutlet.ngOnInit` when it is instantiated
|
|
2663
|
+
context.outlet.attach(stored.componentRef, stored.route.value);
|
|
2664
|
+
}
|
|
2665
|
+
advanceActivatedRoute(stored.route.value);
|
|
2666
|
+
this.activateChildRoutes(futureNode, null, context.children);
|
|
2667
|
+
}
|
|
2668
|
+
else {
|
|
2669
|
+
const injector = getClosestRouteInjector(future.snapshot);
|
|
2670
|
+
const cmpFactoryResolver = injector?.get(ComponentFactoryResolver) ?? null;
|
|
2671
|
+
context.attachRef = null;
|
|
2672
|
+
context.route = future;
|
|
2673
|
+
context.resolver = cmpFactoryResolver;
|
|
2674
|
+
context.injector = injector;
|
|
2675
|
+
if (context.outlet) {
|
|
2676
|
+
// Activate the outlet when it has already been instantiated
|
|
2677
|
+
// Otherwise it will get activated from its `ngOnInit` when instantiated
|
|
2678
|
+
context.outlet.activateWith(future, context.injector);
|
|
2679
|
+
}
|
|
2680
|
+
this.activateChildRoutes(futureNode, null, context.children);
|
|
2681
|
+
}
|
|
2682
|
+
}
|
|
2683
|
+
else {
|
|
2684
|
+
// if we have a componentless route, we recurse but keep the same outlet map.
|
|
2685
|
+
this.activateChildRoutes(futureNode, null, parentContexts);
|
|
2686
|
+
}
|
|
2687
|
+
}
|
|
2564
2688
|
}
|
|
2565
2689
|
}
|
|
2566
2690
|
|
|
@@ -2572,22 +2696,39 @@ class OutletInjector {
|
|
|
2572
2696
|
* found in the LICENSE file at https://angular.io/license
|
|
2573
2697
|
*/
|
|
2574
2698
|
/**
|
|
2575
|
-
*
|
|
2576
|
-
* router-outlet is needed. For example, with a config such as:
|
|
2699
|
+
* Simple function check, but generic so type inference will flow. Example:
|
|
2577
2700
|
*
|
|
2578
|
-
*
|
|
2701
|
+
* function product(a: number, b: number) {
|
|
2702
|
+
* return a * b;
|
|
2703
|
+
* }
|
|
2579
2704
|
*
|
|
2580
|
-
*
|
|
2581
|
-
*
|
|
2705
|
+
* if (isFunction<product>(fn)) {
|
|
2706
|
+
* return fn(1, 2);
|
|
2707
|
+
* } else {
|
|
2708
|
+
* throw "Must provide the `product` function";
|
|
2709
|
+
* }
|
|
2582
2710
|
*/
|
|
2583
|
-
|
|
2711
|
+
function isFunction(v) {
|
|
2712
|
+
return typeof v === 'function';
|
|
2713
|
+
}
|
|
2714
|
+
function isBoolean(v) {
|
|
2715
|
+
return typeof v === 'boolean';
|
|
2716
|
+
}
|
|
2717
|
+
function isUrlTree(v) {
|
|
2718
|
+
return v instanceof UrlTree;
|
|
2719
|
+
}
|
|
2720
|
+
function isCanLoad(guard) {
|
|
2721
|
+
return guard && isFunction(guard.canLoad);
|
|
2722
|
+
}
|
|
2723
|
+
function isCanActivate(guard) {
|
|
2724
|
+
return guard && isFunction(guard.canActivate);
|
|
2725
|
+
}
|
|
2726
|
+
function isCanActivateChild(guard) {
|
|
2727
|
+
return guard && isFunction(guard.canActivateChild);
|
|
2728
|
+
}
|
|
2729
|
+
function isCanDeactivate(guard) {
|
|
2730
|
+
return guard && isFunction(guard.canDeactivate);
|
|
2584
2731
|
}
|
|
2585
|
-
ɵEmptyOutletComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.12", ngImport: i0, type: ɵEmptyOutletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2586
|
-
ɵEmptyOutletComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "14.0.0-next.12", type: ɵEmptyOutletComponent, selector: "ng-component", ngImport: i0, template: `<router-outlet></router-outlet>`, isInline: true, directives: [{ type: RouterOutlet, selector: "router-outlet", outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }] });
|
|
2587
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.12", ngImport: i0, type: ɵEmptyOutletComponent, decorators: [{
|
|
2588
|
-
type: Component,
|
|
2589
|
-
args: [{ template: `<router-outlet></router-outlet>` }]
|
|
2590
|
-
}] });
|
|
2591
2732
|
|
|
2592
2733
|
/**
|
|
2593
2734
|
* @license
|
|
@@ -2596,113 +2737,36 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.12",
|
|
|
2596
2737
|
* Use of this source code is governed by an MIT-style license that can be
|
|
2597
2738
|
* found in the LICENSE file at https://angular.io/license
|
|
2598
2739
|
*/
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
if (route.redirectTo && route.children) {
|
|
2630
|
-
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and children cannot be used together`);
|
|
2631
|
-
}
|
|
2632
|
-
if (route.redirectTo && route.loadChildren) {
|
|
2633
|
-
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and loadChildren cannot be used together`);
|
|
2634
|
-
}
|
|
2635
|
-
if (route.children && route.loadChildren) {
|
|
2636
|
-
throw new Error(`Invalid configuration of route '${fullPath}': children and loadChildren cannot be used together`);
|
|
2637
|
-
}
|
|
2638
|
-
if (route.redirectTo && route.component) {
|
|
2639
|
-
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and component cannot be used together`);
|
|
2640
|
-
}
|
|
2641
|
-
if (route.redirectTo && route.canActivate) {
|
|
2642
|
-
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and canActivate cannot be used together. Redirects happen before activation ` +
|
|
2643
|
-
`so canActivate will never be executed.`);
|
|
2644
|
-
}
|
|
2645
|
-
if (route.path && route.matcher) {
|
|
2646
|
-
throw new Error(`Invalid configuration of route '${fullPath}': path and matcher cannot be used together`);
|
|
2647
|
-
}
|
|
2648
|
-
if (route.redirectTo === void 0 && !route.component && !route.children && !route.loadChildren) {
|
|
2649
|
-
throw new Error(`Invalid configuration of route '${fullPath}'. One of the following must be provided: component, redirectTo, children or loadChildren`);
|
|
2650
|
-
}
|
|
2651
|
-
if (route.path === void 0 && route.matcher === void 0) {
|
|
2652
|
-
throw new Error(`Invalid configuration of route '${fullPath}': routes must have either a path or a matcher specified`);
|
|
2653
|
-
}
|
|
2654
|
-
if (typeof route.path === 'string' && route.path.charAt(0) === '/') {
|
|
2655
|
-
throw new Error(`Invalid configuration of route '${fullPath}': path cannot start with a slash`);
|
|
2656
|
-
}
|
|
2657
|
-
if (route.path === '' && route.redirectTo !== void 0 && route.pathMatch === void 0) {
|
|
2658
|
-
const exp = `The default value of 'pathMatch' is 'prefix', but often the intent is to use 'full'.`;
|
|
2659
|
-
throw new Error(`Invalid configuration of route '{path: "${fullPath}", redirectTo: "${route.redirectTo}"}': please provide 'pathMatch'. ${exp}`);
|
|
2660
|
-
}
|
|
2661
|
-
}
|
|
2662
|
-
if (route.children) {
|
|
2663
|
-
validateConfig(route.children, fullPath);
|
|
2664
|
-
}
|
|
2665
|
-
}
|
|
2666
|
-
function getFullPath(parentPath, currentRoute) {
|
|
2667
|
-
if (!currentRoute) {
|
|
2668
|
-
return parentPath;
|
|
2669
|
-
}
|
|
2670
|
-
if (!parentPath && !currentRoute.path) {
|
|
2671
|
-
return '';
|
|
2672
|
-
}
|
|
2673
|
-
else if (parentPath && !currentRoute.path) {
|
|
2674
|
-
return `${parentPath}/`;
|
|
2675
|
-
}
|
|
2676
|
-
else if (!parentPath && currentRoute.path) {
|
|
2677
|
-
return currentRoute.path;
|
|
2678
|
-
}
|
|
2679
|
-
else {
|
|
2680
|
-
return `${parentPath}/${currentRoute.path}`;
|
|
2681
|
-
}
|
|
2682
|
-
}
|
|
2683
|
-
/**
|
|
2684
|
-
* Makes a copy of the config and adds any default required properties.
|
|
2685
|
-
*/
|
|
2686
|
-
function standardizeConfig(r) {
|
|
2687
|
-
const children = r.children && r.children.map(standardizeConfig);
|
|
2688
|
-
const c = children ? { ...r, children } : { ...r };
|
|
2689
|
-
if (!c.component && (children || c.loadChildren) && (c.outlet && c.outlet !== PRIMARY_OUTLET)) {
|
|
2690
|
-
c.component = ɵEmptyOutletComponent;
|
|
2691
|
-
}
|
|
2692
|
-
return c;
|
|
2693
|
-
}
|
|
2694
|
-
/** Returns the `route.outlet` or PRIMARY_OUTLET if none exists. */
|
|
2695
|
-
function getOutlet(route) {
|
|
2696
|
-
return route.outlet || PRIMARY_OUTLET;
|
|
2697
|
-
}
|
|
2698
|
-
/**
|
|
2699
|
-
* Sorts the `routes` such that the ones with an outlet matching `outletName` come first.
|
|
2700
|
-
* The order of the configs is otherwise preserved.
|
|
2701
|
-
*/
|
|
2702
|
-
function sortByMatchingOutlets(routes, outletName) {
|
|
2703
|
-
const sortedConfig = routes.filter(r => getOutlet(r) === outletName);
|
|
2704
|
-
sortedConfig.push(...routes.filter(r => getOutlet(r) !== outletName));
|
|
2705
|
-
return sortedConfig;
|
|
2740
|
+
const INITIAL_VALUE = Symbol('INITIAL_VALUE');
|
|
2741
|
+
function prioritizedGuardValue() {
|
|
2742
|
+
return switchMap(obs => {
|
|
2743
|
+
return combineLatest(obs.map(o => o.pipe(take(1), startWith(INITIAL_VALUE))))
|
|
2744
|
+
.pipe(scan((acc, list) => {
|
|
2745
|
+
let isPending = false;
|
|
2746
|
+
return list.reduce((innerAcc, val, i) => {
|
|
2747
|
+
if (innerAcc !== INITIAL_VALUE)
|
|
2748
|
+
return innerAcc;
|
|
2749
|
+
// Toggle pending flag if any values haven't been set yet
|
|
2750
|
+
if (val === INITIAL_VALUE)
|
|
2751
|
+
isPending = true;
|
|
2752
|
+
// Any other return values are only valid if we haven't yet hit a pending
|
|
2753
|
+
// call. This guarantees that in the case of a guard at the bottom of the
|
|
2754
|
+
// tree that returns a redirect, we will wait for the higher priority
|
|
2755
|
+
// guard at the top to finish before performing the redirect.
|
|
2756
|
+
if (!isPending) {
|
|
2757
|
+
// Early return when we hit a `false` value as that should always
|
|
2758
|
+
// cancel navigation
|
|
2759
|
+
if (val === false)
|
|
2760
|
+
return val;
|
|
2761
|
+
if (i === list.length - 1 || isUrlTree(val)) {
|
|
2762
|
+
return val;
|
|
2763
|
+
}
|
|
2764
|
+
}
|
|
2765
|
+
return innerAcc;
|
|
2766
|
+
}, acc);
|
|
2767
|
+
}, INITIAL_VALUE), filter(item => item !== INITIAL_VALUE), map(item => isUrlTree(item) ? item : item === true), //
|
|
2768
|
+
take(1));
|
|
2769
|
+
});
|
|
2706
2770
|
}
|
|
2707
2771
|
|
|
2708
2772
|
/**
|
|
@@ -2780,6 +2844,9 @@ function addEmptyPathsToChildrenIfNeeded(segmentGroup, consumedSegments, slicedS
|
|
|
2780
2844
|
s._sourceSegment = segmentGroup;
|
|
2781
2845
|
if (relativeLinkResolution === 'legacy') {
|
|
2782
2846
|
s._segmentIndexShift = segmentGroup.segments.length;
|
|
2847
|
+
if (typeof ngDevMode === 'undefined' || !!ngDevMode) {
|
|
2848
|
+
s._segmentIndexShiftCorrected = consumedSegments.length;
|
|
2849
|
+
}
|
|
2783
2850
|
}
|
|
2784
2851
|
else {
|
|
2785
2852
|
s._segmentIndexShift = consumedSegments.length;
|
|
@@ -2880,17 +2947,17 @@ function canLoadFails(route) {
|
|
|
2880
2947
|
*
|
|
2881
2948
|
* Lazy modules are loaded along the way.
|
|
2882
2949
|
*/
|
|
2883
|
-
function applyRedirects$1(
|
|
2884
|
-
return new ApplyRedirects(
|
|
2950
|
+
function applyRedirects$1(injector, configLoader, urlSerializer, urlTree, config) {
|
|
2951
|
+
return new ApplyRedirects(injector, configLoader, urlSerializer, urlTree, config).apply();
|
|
2885
2952
|
}
|
|
2886
2953
|
class ApplyRedirects {
|
|
2887
|
-
constructor(
|
|
2954
|
+
constructor(injector, configLoader, urlSerializer, urlTree, config) {
|
|
2955
|
+
this.injector = injector;
|
|
2888
2956
|
this.configLoader = configLoader;
|
|
2889
2957
|
this.urlSerializer = urlSerializer;
|
|
2890
2958
|
this.urlTree = urlTree;
|
|
2891
2959
|
this.config = config;
|
|
2892
2960
|
this.allowRedirects = true;
|
|
2893
|
-
this.ngModule = moduleInjector.get(NgModuleRef);
|
|
2894
2961
|
}
|
|
2895
2962
|
apply() {
|
|
2896
2963
|
const splitGroup = split(this.urlTree.root, [], [], this.config).segmentGroup;
|
|
@@ -2901,7 +2968,7 @@ class ApplyRedirects {
|
|
|
2901
2968
|
// them. We should be able to remove this logic as a "breaking change" but should do some more
|
|
2902
2969
|
// investigation into the failures first.
|
|
2903
2970
|
const rootSegmentGroup = new UrlSegmentGroup(splitGroup.segments, splitGroup.children);
|
|
2904
|
-
const expanded$ = this.expandSegmentGroup(this.
|
|
2971
|
+
const expanded$ = this.expandSegmentGroup(this.injector, this.config, rootSegmentGroup, PRIMARY_OUTLET);
|
|
2905
2972
|
const urlTrees$ = expanded$.pipe(map((rootSegmentGroup) => {
|
|
2906
2973
|
return this.createUrlTree(squashSegmentGroup(rootSegmentGroup), this.urlTree.queryParams, this.urlTree.fragment);
|
|
2907
2974
|
}));
|
|
@@ -2920,7 +2987,7 @@ class ApplyRedirects {
|
|
|
2920
2987
|
}));
|
|
2921
2988
|
}
|
|
2922
2989
|
match(tree) {
|
|
2923
|
-
const expanded$ = this.expandSegmentGroup(this.
|
|
2990
|
+
const expanded$ = this.expandSegmentGroup(this.injector, this.config, tree.root, PRIMARY_OUTLET);
|
|
2924
2991
|
const mapped$ = expanded$.pipe(map((rootSegmentGroup) => {
|
|
2925
2992
|
return this.createUrlTree(squashSegmentGroup(rootSegmentGroup), tree.queryParams, tree.fragment);
|
|
2926
2993
|
}));
|
|
@@ -2940,15 +3007,15 @@ class ApplyRedirects {
|
|
|
2940
3007
|
rootCandidate;
|
|
2941
3008
|
return new UrlTree(root, queryParams, fragment);
|
|
2942
3009
|
}
|
|
2943
|
-
expandSegmentGroup(
|
|
3010
|
+
expandSegmentGroup(injector, routes, segmentGroup, outlet) {
|
|
2944
3011
|
if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) {
|
|
2945
|
-
return this.expandChildren(
|
|
3012
|
+
return this.expandChildren(injector, routes, segmentGroup)
|
|
2946
3013
|
.pipe(map((children) => new UrlSegmentGroup([], children)));
|
|
2947
3014
|
}
|
|
2948
|
-
return this.expandSegment(
|
|
3015
|
+
return this.expandSegment(injector, segmentGroup, routes, segmentGroup.segments, outlet, true);
|
|
2949
3016
|
}
|
|
2950
3017
|
// Recursively expand segment groups for all the child outlets
|
|
2951
|
-
expandChildren(
|
|
3018
|
+
expandChildren(injector, routes, segmentGroup) {
|
|
2952
3019
|
// Expand outlets one at a time, starting with the primary outlet. We need to do it this way
|
|
2953
3020
|
// because an absolute redirect from the primary outlet takes precedence.
|
|
2954
3021
|
const childOutlets = [];
|
|
@@ -2967,16 +3034,25 @@ class ApplyRedirects {
|
|
|
2967
3034
|
// first, followed by routes for other outlets, which might match if they have an
|
|
2968
3035
|
// empty path.
|
|
2969
3036
|
const sortedRoutes = sortByMatchingOutlets(routes, childOutlet);
|
|
2970
|
-
return this.expandSegmentGroup(
|
|
3037
|
+
return this.expandSegmentGroup(injector, sortedRoutes, child, childOutlet)
|
|
2971
3038
|
.pipe(map(s => ({ segment: s, outlet: childOutlet })));
|
|
2972
3039
|
}), scan((children, expandedChild) => {
|
|
2973
3040
|
children[expandedChild.outlet] = expandedChild.segment;
|
|
2974
3041
|
return children;
|
|
2975
3042
|
}, {}), last$1());
|
|
2976
3043
|
}
|
|
2977
|
-
expandSegment(
|
|
2978
|
-
return from(routes).pipe(concatMap(
|
|
2979
|
-
|
|
3044
|
+
expandSegment(injector, segmentGroup, routes, segments, outlet, allowRedirects) {
|
|
3045
|
+
return from(routes).pipe(concatMap(r => {
|
|
3046
|
+
if (r.providers && !r._injector) {
|
|
3047
|
+
r._injector = createEnvironmentInjector(r.providers, injector, `Route: ${r.path}`);
|
|
3048
|
+
}
|
|
3049
|
+
// We specifically _do not_ want to include the _loadedInjector here. The loaded injector
|
|
3050
|
+
// only applies to the route's children, not the route itself. Note that this distinction
|
|
3051
|
+
// only applies here to any tokens we try to retrieve during this phase. At the moment,
|
|
3052
|
+
// that only includes `canLoad`, which won't run again once the child module is loaded. As
|
|
3053
|
+
// a result, this makes no difference right now, but could in the future if there are more
|
|
3054
|
+
// actions here that need DI (for example, a canMatch guard).
|
|
3055
|
+
const expanded$ = this.expandSegmentAgainstRoute(r._injector ?? injector, segmentGroup, routes, r, segments, outlet, allowRedirects);
|
|
2980
3056
|
return expanded$.pipe(catchError((e) => {
|
|
2981
3057
|
if (e instanceof NoMatch$1) {
|
|
2982
3058
|
return of(null);
|
|
@@ -2993,35 +3069,35 @@ class ApplyRedirects {
|
|
|
2993
3069
|
throw e;
|
|
2994
3070
|
}));
|
|
2995
3071
|
}
|
|
2996
|
-
expandSegmentAgainstRoute(
|
|
3072
|
+
expandSegmentAgainstRoute(injector, segmentGroup, routes, route, paths, outlet, allowRedirects) {
|
|
2997
3073
|
if (!isImmediateMatch(route, segmentGroup, paths, outlet)) {
|
|
2998
3074
|
return noMatch(segmentGroup);
|
|
2999
3075
|
}
|
|
3000
3076
|
if (route.redirectTo === undefined) {
|
|
3001
|
-
return this.matchSegmentAgainstRoute(
|
|
3077
|
+
return this.matchSegmentAgainstRoute(injector, segmentGroup, route, paths, outlet);
|
|
3002
3078
|
}
|
|
3003
3079
|
if (allowRedirects && this.allowRedirects) {
|
|
3004
|
-
return this.expandSegmentAgainstRouteUsingRedirect(
|
|
3080
|
+
return this.expandSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, paths, outlet);
|
|
3005
3081
|
}
|
|
3006
3082
|
return noMatch(segmentGroup);
|
|
3007
3083
|
}
|
|
3008
|
-
expandSegmentAgainstRouteUsingRedirect(
|
|
3084
|
+
expandSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet) {
|
|
3009
3085
|
if (route.path === '**') {
|
|
3010
|
-
return this.expandWildCardWithParamsAgainstRouteUsingRedirect(
|
|
3086
|
+
return this.expandWildCardWithParamsAgainstRouteUsingRedirect(injector, routes, route, outlet);
|
|
3011
3087
|
}
|
|
3012
|
-
return this.expandRegularSegmentAgainstRouteUsingRedirect(
|
|
3088
|
+
return this.expandRegularSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet);
|
|
3013
3089
|
}
|
|
3014
|
-
expandWildCardWithParamsAgainstRouteUsingRedirect(
|
|
3090
|
+
expandWildCardWithParamsAgainstRouteUsingRedirect(injector, routes, route, outlet) {
|
|
3015
3091
|
const newTree = this.applyRedirectCommands([], route.redirectTo, {});
|
|
3016
3092
|
if (route.redirectTo.startsWith('/')) {
|
|
3017
3093
|
return absoluteRedirect(newTree);
|
|
3018
3094
|
}
|
|
3019
3095
|
return this.lineralizeSegments(route, newTree).pipe(mergeMap((newSegments) => {
|
|
3020
3096
|
const group = new UrlSegmentGroup(newSegments, {});
|
|
3021
|
-
return this.expandSegment(
|
|
3097
|
+
return this.expandSegment(injector, group, routes, newSegments, outlet, false);
|
|
3022
3098
|
}));
|
|
3023
3099
|
}
|
|
3024
|
-
expandRegularSegmentAgainstRouteUsingRedirect(
|
|
3100
|
+
expandRegularSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet) {
|
|
3025
3101
|
const { matched, consumedSegments, remainingSegments, positionalParamSegments } = match(segmentGroup, route, segments);
|
|
3026
3102
|
if (!matched)
|
|
3027
3103
|
return noMatch(segmentGroup);
|
|
@@ -3030,16 +3106,18 @@ class ApplyRedirects {
|
|
|
3030
3106
|
return absoluteRedirect(newTree);
|
|
3031
3107
|
}
|
|
3032
3108
|
return this.lineralizeSegments(route, newTree).pipe(mergeMap((newSegments) => {
|
|
3033
|
-
return this.expandSegment(
|
|
3109
|
+
return this.expandSegment(injector, segmentGroup, routes, newSegments.concat(remainingSegments), outlet, false);
|
|
3034
3110
|
}));
|
|
3035
3111
|
}
|
|
3036
|
-
matchSegmentAgainstRoute(
|
|
3112
|
+
matchSegmentAgainstRoute(injector, rawSegmentGroup, route, segments, outlet) {
|
|
3037
3113
|
if (route.path === '**') {
|
|
3038
3114
|
if (route.loadChildren) {
|
|
3039
|
-
const loaded$ = route.
|
|
3040
|
-
|
|
3115
|
+
const loaded$ = route._loadedRoutes ?
|
|
3116
|
+
of({ routes: route._loadedRoutes, injector: route._loadedInjector }) :
|
|
3117
|
+
this.configLoader.loadChildren(injector, route);
|
|
3041
3118
|
return loaded$.pipe(map((cfg) => {
|
|
3042
|
-
route.
|
|
3119
|
+
route._loadedRoutes = cfg.routes;
|
|
3120
|
+
route._loadedInjector = cfg.injector;
|
|
3043
3121
|
return new UrlSegmentGroup(segments, {});
|
|
3044
3122
|
}));
|
|
3045
3123
|
}
|
|
@@ -3048,55 +3126,55 @@ class ApplyRedirects {
|
|
|
3048
3126
|
const { matched, consumedSegments, remainingSegments } = match(rawSegmentGroup, route, segments);
|
|
3049
3127
|
if (!matched)
|
|
3050
3128
|
return noMatch(rawSegmentGroup);
|
|
3051
|
-
const childConfig$ = this.getChildConfig(
|
|
3129
|
+
const childConfig$ = this.getChildConfig(injector, route, segments);
|
|
3052
3130
|
return childConfig$.pipe(mergeMap((routerConfig) => {
|
|
3053
|
-
const
|
|
3131
|
+
const childInjector = routerConfig.injector ?? injector;
|
|
3054
3132
|
const childConfig = routerConfig.routes;
|
|
3055
3133
|
const { segmentGroup: splitSegmentGroup, slicedSegments } = split(rawSegmentGroup, consumedSegments, remainingSegments, childConfig);
|
|
3056
3134
|
// See comment on the other call to `split` about why this is necessary.
|
|
3057
3135
|
const segmentGroup = new UrlSegmentGroup(splitSegmentGroup.segments, splitSegmentGroup.children);
|
|
3058
3136
|
if (slicedSegments.length === 0 && segmentGroup.hasChildren()) {
|
|
3059
|
-
const expanded$ = this.expandChildren(
|
|
3137
|
+
const expanded$ = this.expandChildren(childInjector, childConfig, segmentGroup);
|
|
3060
3138
|
return expanded$.pipe(map((children) => new UrlSegmentGroup(consumedSegments, children)));
|
|
3061
3139
|
}
|
|
3062
3140
|
if (childConfig.length === 0 && slicedSegments.length === 0) {
|
|
3063
3141
|
return of(new UrlSegmentGroup(consumedSegments, {}));
|
|
3064
3142
|
}
|
|
3065
3143
|
const matchedOnOutlet = getOutlet(route) === outlet;
|
|
3066
|
-
const expanded$ = this.expandSegment(
|
|
3144
|
+
const expanded$ = this.expandSegment(childInjector, segmentGroup, childConfig, slicedSegments, matchedOnOutlet ? PRIMARY_OUTLET : outlet, true);
|
|
3067
3145
|
return expanded$.pipe(map((cs) => new UrlSegmentGroup(consumedSegments.concat(cs.segments), cs.children)));
|
|
3068
3146
|
}));
|
|
3069
3147
|
}
|
|
3070
|
-
getChildConfig(
|
|
3148
|
+
getChildConfig(injector, route, segments) {
|
|
3071
3149
|
if (route.children) {
|
|
3072
3150
|
// The children belong to the same module
|
|
3073
|
-
return of(
|
|
3151
|
+
return of({ routes: route.children, injector });
|
|
3074
3152
|
}
|
|
3075
3153
|
if (route.loadChildren) {
|
|
3076
3154
|
// lazy children belong to the loaded module
|
|
3077
|
-
if (route.
|
|
3078
|
-
return of(route.
|
|
3155
|
+
if (route._loadedRoutes !== undefined) {
|
|
3156
|
+
return of({ routes: route._loadedRoutes, injector: route._loadedInjector });
|
|
3079
3157
|
}
|
|
3080
|
-
return this.runCanLoadGuards(
|
|
3158
|
+
return this.runCanLoadGuards(injector, route, segments)
|
|
3081
3159
|
.pipe(mergeMap((shouldLoadResult) => {
|
|
3082
3160
|
if (shouldLoadResult) {
|
|
3083
|
-
return this.configLoader.
|
|
3084
|
-
.pipe(
|
|
3085
|
-
route.
|
|
3086
|
-
|
|
3161
|
+
return this.configLoader.loadChildren(injector, route)
|
|
3162
|
+
.pipe(tap((cfg) => {
|
|
3163
|
+
route._loadedRoutes = cfg.routes;
|
|
3164
|
+
route._loadedInjector = cfg.injector;
|
|
3087
3165
|
}));
|
|
3088
3166
|
}
|
|
3089
3167
|
return canLoadFails(route);
|
|
3090
3168
|
}));
|
|
3091
3169
|
}
|
|
3092
|
-
return of(
|
|
3170
|
+
return of({ routes: [], injector });
|
|
3093
3171
|
}
|
|
3094
|
-
runCanLoadGuards(
|
|
3172
|
+
runCanLoadGuards(injector, route, segments) {
|
|
3095
3173
|
const canLoad = route.canLoad;
|
|
3096
3174
|
if (!canLoad || canLoad.length === 0)
|
|
3097
3175
|
return of(true);
|
|
3098
3176
|
const canLoadObservables = canLoad.map((injectionToken) => {
|
|
3099
|
-
const guard =
|
|
3177
|
+
const guard = injector.get(injectionToken);
|
|
3100
3178
|
let guardVal;
|
|
3101
3179
|
if (isCanLoad(guard)) {
|
|
3102
3180
|
guardVal = guard.canLoad(route, segments);
|
|
@@ -3224,8 +3302,8 @@ function squashSegmentGroup(segmentGroup) {
|
|
|
3224
3302
|
* Use of this source code is governed by an MIT-style license that can be
|
|
3225
3303
|
* found in the LICENSE file at https://angular.io/license
|
|
3226
3304
|
*/
|
|
3227
|
-
function applyRedirects(
|
|
3228
|
-
return switchMap(t => applyRedirects$1(
|
|
3305
|
+
function applyRedirects(environmentInjector, configLoader, urlSerializer, config) {
|
|
3306
|
+
return switchMap(t => applyRedirects$1(environmentInjector, configLoader, urlSerializer, t.extractedUrl, config)
|
|
3229
3307
|
.pipe(map(urlAfterRedirects => ({ ...t, urlAfterRedirects }))));
|
|
3230
3308
|
}
|
|
3231
3309
|
|
|
@@ -3259,21 +3337,11 @@ function getCanActivateChild(p) {
|
|
|
3259
3337
|
return null;
|
|
3260
3338
|
return { node: p, guards: canActivateChild };
|
|
3261
3339
|
}
|
|
3262
|
-
function getToken(token, snapshot,
|
|
3263
|
-
const
|
|
3264
|
-
const injector =
|
|
3340
|
+
function getToken(token, snapshot, fallbackInjector) {
|
|
3341
|
+
const routeInjector = getClosestRouteInjector(snapshot);
|
|
3342
|
+
const injector = routeInjector ?? fallbackInjector;
|
|
3265
3343
|
return injector.get(token);
|
|
3266
3344
|
}
|
|
3267
|
-
function getClosestLoadedConfig(snapshot) {
|
|
3268
|
-
if (!snapshot)
|
|
3269
|
-
return null;
|
|
3270
|
-
for (let s = snapshot.parent; s; s = s.parent) {
|
|
3271
|
-
const route = s.routeConfig;
|
|
3272
|
-
if (route && route._loadedConfig)
|
|
3273
|
-
return route._loadedConfig;
|
|
3274
|
-
}
|
|
3275
|
-
return null;
|
|
3276
|
-
}
|
|
3277
3345
|
function getChildRouteGuards(futureNode, currNode, contexts, futurePath, checks = {
|
|
3278
3346
|
canDeactivateChecks: [],
|
|
3279
3347
|
canActivateChecks: []
|
|
@@ -3517,6 +3585,7 @@ function runCanDeactivate(component, currARS, currRSS, futureRSS, moduleInjector
|
|
|
3517
3585
|
* Use of this source code is governed by an MIT-style license that can be
|
|
3518
3586
|
* found in the LICENSE file at https://angular.io/license
|
|
3519
3587
|
*/
|
|
3588
|
+
const NG_DEV_MODE$2 = typeof ngDevMode === 'undefined' || !!ngDevMode;
|
|
3520
3589
|
class NoMatch {
|
|
3521
3590
|
}
|
|
3522
3591
|
function newObservableError(e) {
|
|
@@ -3632,7 +3701,13 @@ class Recognizer {
|
|
|
3632
3701
|
let remainingSegments = [];
|
|
3633
3702
|
if (route.path === '**') {
|
|
3634
3703
|
const params = segments.length > 0 ? last(segments).parameters : {};
|
|
3635
|
-
|
|
3704
|
+
const pathIndexShift = getPathIndexShift(rawSegment) + segments.length;
|
|
3705
|
+
snapshot = new ActivatedRouteSnapshot(segments, params, Object.freeze({ ...this.urlTree.queryParams }), this.urlTree.fragment, getData(route), getOutlet(route), route.component ?? route._loadedComponent ?? null, route, getSourceSegmentGroup(rawSegment), pathIndexShift, getResolve(route),
|
|
3706
|
+
// NG_DEV_MODE is used to prevent the getCorrectedPathIndexShift function from affecting
|
|
3707
|
+
// production bundle size. This value is intended only to surface a warning to users
|
|
3708
|
+
// depending on `relativeLinkResolution: 'legacy'` in dev mode.
|
|
3709
|
+
(NG_DEV_MODE$2 ? getCorrectedPathIndexShift(rawSegment) + segments.length :
|
|
3710
|
+
pathIndexShift));
|
|
3636
3711
|
}
|
|
3637
3712
|
else {
|
|
3638
3713
|
const result = match(rawSegment, route, segments);
|
|
@@ -3641,7 +3716,9 @@ class Recognizer {
|
|
|
3641
3716
|
}
|
|
3642
3717
|
consumedSegments = result.consumedSegments;
|
|
3643
3718
|
remainingSegments = result.remainingSegments;
|
|
3644
|
-
|
|
3719
|
+
const pathIndexShift = getPathIndexShift(rawSegment) + consumedSegments.length;
|
|
3720
|
+
snapshot = new ActivatedRouteSnapshot(consumedSegments, result.parameters, Object.freeze({ ...this.urlTree.queryParams }), this.urlTree.fragment, getData(route), getOutlet(route), route.component ?? route._loadedComponent ?? null, route, getSourceSegmentGroup(rawSegment), pathIndexShift, getResolve(route), (NG_DEV_MODE$2 ? getCorrectedPathIndexShift(rawSegment) + consumedSegments.length :
|
|
3721
|
+
pathIndexShift));
|
|
3645
3722
|
}
|
|
3646
3723
|
const childConfig = getChildConfig(route);
|
|
3647
3724
|
const { segmentGroup, slicedSegments } = split(rawSegment, consumedSegments, remainingSegments,
|
|
@@ -3689,7 +3766,7 @@ function getChildConfig(route) {
|
|
|
3689
3766
|
return route.children;
|
|
3690
3767
|
}
|
|
3691
3768
|
if (route.loadChildren) {
|
|
3692
|
-
return route.
|
|
3769
|
+
return route._loadedRoutes;
|
|
3693
3770
|
}
|
|
3694
3771
|
return [];
|
|
3695
3772
|
}
|
|
@@ -3751,10 +3828,19 @@ function getSourceSegmentGroup(segmentGroup) {
|
|
|
3751
3828
|
}
|
|
3752
3829
|
function getPathIndexShift(segmentGroup) {
|
|
3753
3830
|
let s = segmentGroup;
|
|
3754
|
-
let res =
|
|
3831
|
+
let res = s._segmentIndexShift ?? 0;
|
|
3832
|
+
while (s._sourceSegment) {
|
|
3833
|
+
s = s._sourceSegment;
|
|
3834
|
+
res += s._segmentIndexShift ?? 0;
|
|
3835
|
+
}
|
|
3836
|
+
return res - 1;
|
|
3837
|
+
}
|
|
3838
|
+
function getCorrectedPathIndexShift(segmentGroup) {
|
|
3839
|
+
let s = segmentGroup;
|
|
3840
|
+
let res = s._segmentIndexShiftCorrected ?? s._segmentIndexShift ?? 0;
|
|
3755
3841
|
while (s._sourceSegment) {
|
|
3756
3842
|
s = s._sourceSegment;
|
|
3757
|
-
res +=
|
|
3843
|
+
res += s._segmentIndexShiftCorrected ?? s._segmentIndexShift ?? 0;
|
|
3758
3844
|
}
|
|
3759
3845
|
return res - 1;
|
|
3760
3846
|
}
|
|
@@ -3824,16 +3910,9 @@ function resolveNode(resolve, futureARS, futureRSS, moduleInjector) {
|
|
|
3824
3910
|
}
|
|
3825
3911
|
const data = {};
|
|
3826
3912
|
return from(keys).pipe(mergeMap(key => getResolver(resolve[key], futureARS, futureRSS, moduleInjector)
|
|
3827
|
-
.pipe(
|
|
3913
|
+
.pipe(first(), tap((value) => {
|
|
3828
3914
|
data[key] = value;
|
|
3829
|
-
}))), takeLast(1),
|
|
3830
|
-
// Ensure all resolvers returned values, otherwise don't emit any "next" and just complete
|
|
3831
|
-
// the chain which will cancel navigation
|
|
3832
|
-
if (getDataKeys(data).length === keys.length) {
|
|
3833
|
-
return of(data);
|
|
3834
|
-
}
|
|
3835
|
-
return EMPTY;
|
|
3836
|
-
}));
|
|
3915
|
+
}))), takeLast(1), mapTo(data), catchError((e) => e instanceof EmptyError ? EMPTY : throwError(e)));
|
|
3837
3916
|
}
|
|
3838
3917
|
function getDataKeys(obj) {
|
|
3839
3918
|
return [...Object.keys(obj), ...Object.getOwnPropertySymbols(obj)];
|
|
@@ -3942,6 +4021,7 @@ class DefaultRouteReuseStrategy extends BaseRouteReuseStrategy {
|
|
|
3942
4021
|
* Use of this source code is governed by an MIT-style license that can be
|
|
3943
4022
|
* found in the LICENSE file at https://angular.io/license
|
|
3944
4023
|
*/
|
|
4024
|
+
const NG_DEV_MODE$1 = typeof ngDevMode === 'undefined' || !!ngDevMode;
|
|
3945
4025
|
/**
|
|
3946
4026
|
* The [DI token](guide/glossary/#di-token) for a router configuration.
|
|
3947
4027
|
*
|
|
@@ -3954,43 +4034,84 @@ class DefaultRouteReuseStrategy extends BaseRouteReuseStrategy {
|
|
|
3954
4034
|
*/
|
|
3955
4035
|
const ROUTES = new InjectionToken('ROUTES');
|
|
3956
4036
|
class RouterConfigLoader {
|
|
3957
|
-
constructor(injector, compiler
|
|
4037
|
+
constructor(injector, compiler) {
|
|
3958
4038
|
this.injector = injector;
|
|
3959
4039
|
this.compiler = compiler;
|
|
3960
|
-
this.
|
|
3961
|
-
this.
|
|
4040
|
+
this.componentLoaders = new WeakMap();
|
|
4041
|
+
this.childrenLoaders = new WeakMap();
|
|
4042
|
+
}
|
|
4043
|
+
loadComponent(route) {
|
|
4044
|
+
if (this.componentLoaders.get(route)) {
|
|
4045
|
+
return this.componentLoaders.get(route);
|
|
4046
|
+
}
|
|
4047
|
+
else if (route._loadedComponent) {
|
|
4048
|
+
return of(route._loadedComponent);
|
|
4049
|
+
}
|
|
4050
|
+
if (this.onLoadStartListener) {
|
|
4051
|
+
this.onLoadStartListener(route);
|
|
4052
|
+
}
|
|
4053
|
+
const loadRunner = wrapIntoObservable(route.loadComponent())
|
|
4054
|
+
.pipe(tap(component => {
|
|
4055
|
+
if (this.onLoadEndListener) {
|
|
4056
|
+
this.onLoadEndListener(route);
|
|
4057
|
+
}
|
|
4058
|
+
NG_DEV_MODE$1 && assertStandalone(route.path ?? '', component);
|
|
4059
|
+
route._loadedComponent = component;
|
|
4060
|
+
}), finalize(() => {
|
|
4061
|
+
this.componentLoaders.delete(route);
|
|
4062
|
+
}));
|
|
4063
|
+
// Use custom ConnectableObservable as share in runners pipe increasing the bundle size too much
|
|
4064
|
+
const loader = new ConnectableObservable(loadRunner, () => new Subject()).pipe(refCount());
|
|
4065
|
+
this.componentLoaders.set(route, loader);
|
|
4066
|
+
return loader;
|
|
3962
4067
|
}
|
|
3963
|
-
|
|
3964
|
-
if (route
|
|
3965
|
-
return route
|
|
4068
|
+
loadChildren(parentInjector, route) {
|
|
4069
|
+
if (this.childrenLoaders.get(route)) {
|
|
4070
|
+
return this.childrenLoaders.get(route);
|
|
4071
|
+
}
|
|
4072
|
+
else if (route._loadedRoutes) {
|
|
4073
|
+
return of({ routes: route._loadedRoutes, injector: route._loadedInjector });
|
|
3966
4074
|
}
|
|
3967
4075
|
if (this.onLoadStartListener) {
|
|
3968
4076
|
this.onLoadStartListener(route);
|
|
3969
4077
|
}
|
|
3970
|
-
const
|
|
3971
|
-
const loadRunner =
|
|
4078
|
+
const moduleFactoryOrRoutes$ = this.loadModuleFactoryOrRoutes(route.loadChildren);
|
|
4079
|
+
const loadRunner = moduleFactoryOrRoutes$.pipe(map((factoryOrRoutes) => {
|
|
3972
4080
|
if (this.onLoadEndListener) {
|
|
3973
4081
|
this.onLoadEndListener(route);
|
|
3974
4082
|
}
|
|
3975
|
-
|
|
3976
|
-
//
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
4083
|
+
// This injector comes from the `NgModuleRef` when lazy loading an `NgModule`. There is no
|
|
4084
|
+
// injector associated with lazy loading a `Route` array.
|
|
4085
|
+
let injector;
|
|
4086
|
+
let rawRoutes;
|
|
4087
|
+
let requireStandaloneComponents = false;
|
|
4088
|
+
if (Array.isArray(factoryOrRoutes)) {
|
|
4089
|
+
rawRoutes = factoryOrRoutes;
|
|
4090
|
+
requireStandaloneComponents = true;
|
|
4091
|
+
}
|
|
4092
|
+
else {
|
|
4093
|
+
injector = factoryOrRoutes.create(parentInjector).injector;
|
|
4094
|
+
// When loading a module that doesn't provide `RouterModule.forChild()` preloader
|
|
4095
|
+
// will get stuck in an infinite loop. The child module's Injector will look to
|
|
4096
|
+
// its parent `Injector` when it doesn't find any ROUTES so it will return routes
|
|
4097
|
+
// for it's parent module instead.
|
|
4098
|
+
rawRoutes = flatten(injector.get(ROUTES, [], InjectFlags.Self | InjectFlags.Optional));
|
|
4099
|
+
}
|
|
4100
|
+
const routes = rawRoutes.map(standardizeConfig);
|
|
4101
|
+
NG_DEV_MODE$1 && validateConfig(routes, route.path, requireStandaloneComponents);
|
|
4102
|
+
return { routes, injector };
|
|
4103
|
+
}), finalize(() => {
|
|
4104
|
+
this.childrenLoaders.delete(route);
|
|
3985
4105
|
}));
|
|
3986
4106
|
// Use custom ConnectableObservable as share in runners pipe increasing the bundle size too much
|
|
3987
|
-
|
|
4107
|
+
const loader = new ConnectableObservable(loadRunner, () => new Subject())
|
|
3988
4108
|
.pipe(refCount());
|
|
3989
|
-
|
|
4109
|
+
this.childrenLoaders.set(route, loader);
|
|
4110
|
+
return loader;
|
|
3990
4111
|
}
|
|
3991
|
-
|
|
4112
|
+
loadModuleFactoryOrRoutes(loadChildren) {
|
|
3992
4113
|
return wrapIntoObservable(loadChildren()).pipe(mergeMap((t) => {
|
|
3993
|
-
if (t instanceof NgModuleFactory) {
|
|
4114
|
+
if (t instanceof NgModuleFactory || Array.isArray(t)) {
|
|
3994
4115
|
return of(t);
|
|
3995
4116
|
}
|
|
3996
4117
|
else {
|
|
@@ -3999,6 +4120,11 @@ class RouterConfigLoader {
|
|
|
3999
4120
|
}));
|
|
4000
4121
|
}
|
|
4001
4122
|
}
|
|
4123
|
+
RouterConfigLoader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: RouterConfigLoader, deps: [{ token: i0.Injector }, { token: i0.Compiler }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
4124
|
+
RouterConfigLoader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: RouterConfigLoader });
|
|
4125
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: RouterConfigLoader, decorators: [{
|
|
4126
|
+
type: Injectable
|
|
4127
|
+
}], ctorParameters: function () { return [{ type: i0.Injector }, { type: i0.Compiler }]; } });
|
|
4002
4128
|
|
|
4003
4129
|
/**
|
|
4004
4130
|
* @license
|
|
@@ -4038,6 +4164,7 @@ class DefaultUrlHandlingStrategy {
|
|
|
4038
4164
|
* Use of this source code is governed by an MIT-style license that can be
|
|
4039
4165
|
* found in the LICENSE file at https://angular.io/license
|
|
4040
4166
|
*/
|
|
4167
|
+
const NG_DEV_MODE = typeof ngDevMode === 'undefined' || !!ngDevMode;
|
|
4041
4168
|
function defaultErrorHandler(error) {
|
|
4042
4169
|
throw error;
|
|
4043
4170
|
}
|
|
@@ -4209,6 +4336,9 @@ class Router {
|
|
|
4209
4336
|
this.canceledNavigationResolution = 'replace';
|
|
4210
4337
|
const onLoadStart = (r) => this.triggerEvent(new RouteConfigLoadStart(r));
|
|
4211
4338
|
const onLoadEnd = (r) => this.triggerEvent(new RouteConfigLoadEnd(r));
|
|
4339
|
+
this.configLoader = injector.get(RouterConfigLoader);
|
|
4340
|
+
this.configLoader.onLoadEndListener = onLoadEnd;
|
|
4341
|
+
this.configLoader.onLoadStartListener = onLoadStart;
|
|
4212
4342
|
this.ngModule = injector.get(NgModuleRef);
|
|
4213
4343
|
this.console = injector.get(ɵConsole);
|
|
4214
4344
|
const ngZone = injector.get(NgZone);
|
|
@@ -4217,7 +4347,6 @@ class Router {
|
|
|
4217
4347
|
this.currentUrlTree = createEmptyUrlTree();
|
|
4218
4348
|
this.rawUrlTree = this.currentUrlTree;
|
|
4219
4349
|
this.browserUrlTree = this.currentUrlTree;
|
|
4220
|
-
this.configLoader = new RouterConfigLoader(injector, compiler, onLoadStart, onLoadEnd);
|
|
4221
4350
|
this.routerState = createEmptyState(this.currentUrlTree, this.rootComponentType);
|
|
4222
4351
|
this.transitions = new BehaviorSubject({
|
|
4223
4352
|
id: 0,
|
|
@@ -4426,6 +4555,25 @@ class Router {
|
|
|
4426
4555
|
skipLocationChange: !!skipLocationChange,
|
|
4427
4556
|
replaceUrl: !!replaceUrl,
|
|
4428
4557
|
});
|
|
4558
|
+
}),
|
|
4559
|
+
// --- LOAD COMPONENTS ---
|
|
4560
|
+
switchTap((t) => {
|
|
4561
|
+
const loadComponents = (route) => {
|
|
4562
|
+
const loaders = [];
|
|
4563
|
+
if (route.routeConfig?.loadComponent &&
|
|
4564
|
+
!route.routeConfig._loadedComponent) {
|
|
4565
|
+
loaders.push(this.configLoader.loadComponent(route.routeConfig)
|
|
4566
|
+
.pipe(tap(loadedComponent => {
|
|
4567
|
+
route.component = loadedComponent;
|
|
4568
|
+
}), map(() => void 0)));
|
|
4569
|
+
}
|
|
4570
|
+
for (const child of route.children) {
|
|
4571
|
+
loaders.push(...loadComponents(child));
|
|
4572
|
+
}
|
|
4573
|
+
return loaders;
|
|
4574
|
+
};
|
|
4575
|
+
return combineLatest(loadComponents(t.targetSnapshot.root))
|
|
4576
|
+
.pipe(defaultIfEmpty(), take(1));
|
|
4429
4577
|
}), map((t) => {
|
|
4430
4578
|
const targetRouterState = createRouterState(this.routeReuseStrategy, t.targetSnapshot, t.currentRouterState);
|
|
4431
4579
|
return ({ ...t, targetRouterState });
|
|
@@ -4504,23 +4652,17 @@ class Router {
|
|
|
4504
4652
|
t.resolve(false);
|
|
4505
4653
|
}
|
|
4506
4654
|
else {
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
|
|
4515
|
-
|
|
4516
|
-
|
|
4517
|
-
|
|
4518
|
-
// the navigation is rejected.
|
|
4519
|
-
replaceUrl: this.urlUpdateStrategy === 'eager' ||
|
|
4520
|
-
isBrowserTriggeredNavigation(t.source)
|
|
4521
|
-
};
|
|
4522
|
-
this.scheduleNavigation(mergedTree, 'imperative', null, extras, { resolve: t.resolve, reject: t.reject, promise: t.promise });
|
|
4523
|
-
}, 0);
|
|
4655
|
+
const mergedTree = this.urlHandlingStrategy.merge(e.url, this.rawUrlTree);
|
|
4656
|
+
const extras = {
|
|
4657
|
+
skipLocationChange: t.extras.skipLocationChange,
|
|
4658
|
+
// The URL is already updated at this point if we have 'eager' URL
|
|
4659
|
+
// updates or if the navigation was triggered by the browser (back
|
|
4660
|
+
// button, URL bar, etc). We want to replace that item in history if
|
|
4661
|
+
// the navigation is rejected.
|
|
4662
|
+
replaceUrl: this.urlUpdateStrategy === 'eager' ||
|
|
4663
|
+
isBrowserTriggeredNavigation(t.source)
|
|
4664
|
+
};
|
|
4665
|
+
this.scheduleNavigation(mergedTree, 'imperative', null, extras, { resolve: t.resolve, reject: t.reject, promise: t.promise });
|
|
4524
4666
|
}
|
|
4525
4667
|
/* All other errors should reset to the router's internal URL reference to
|
|
4526
4668
|
* the pre-error state. */
|
|
@@ -4630,7 +4772,7 @@ class Router {
|
|
|
4630
4772
|
* ```
|
|
4631
4773
|
*/
|
|
4632
4774
|
resetConfig(config) {
|
|
4633
|
-
validateConfig(config);
|
|
4775
|
+
NG_DEV_MODE && validateConfig(config);
|
|
4634
4776
|
this.config = config.map(standardizeConfig);
|
|
4635
4777
|
this.navigated = false;
|
|
4636
4778
|
this.lastSuccessfulId = -1;
|
|
@@ -4985,9 +5127,9 @@ class Router {
|
|
|
4985
5127
|
return { navigationId };
|
|
4986
5128
|
}
|
|
4987
5129
|
}
|
|
4988
|
-
Router.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
4989
|
-
Router.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
4990
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5130
|
+
Router.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: Router, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
|
|
5131
|
+
Router.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: Router });
|
|
5132
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: Router, decorators: [{
|
|
4991
5133
|
type: Injectable
|
|
4992
5134
|
}], ctorParameters: function () { return [{ type: i0.Type }, { type: UrlSerializer }, { type: ChildrenOutletContexts }, { type: i3.Location }, { type: i0.Injector }, { type: i0.Compiler }, { type: undefined }]; } });
|
|
4993
5135
|
function validateCommands(commands) {
|
|
@@ -5186,9 +5328,9 @@ class RouterLink {
|
|
|
5186
5328
|
});
|
|
5187
5329
|
}
|
|
5188
5330
|
}
|
|
5189
|
-
RouterLink.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5190
|
-
RouterLink.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5191
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5331
|
+
RouterLink.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: RouterLink, deps: [{ token: Router }, { token: ActivatedRoute }, { token: 'tabindex', attribute: true }, { token: i0.Renderer2 }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
|
|
5332
|
+
RouterLink.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.15", type: RouterLink, selector: ":not(a):not(area)[routerLink]", inputs: { queryParams: "queryParams", fragment: "fragment", queryParamsHandling: "queryParamsHandling", preserveFragment: "preserveFragment", skipLocationChange: "skipLocationChange", replaceUrl: "replaceUrl", state: "state", relativeTo: "relativeTo", routerLink: "routerLink" }, host: { listeners: { "click": "onClick()" } }, usesOnChanges: true, ngImport: i0 });
|
|
5333
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: RouterLink, decorators: [{
|
|
5192
5334
|
type: Directive,
|
|
5193
5335
|
args: [{ selector: ':not(a):not(area)[routerLink]' }]
|
|
5194
5336
|
}], ctorParameters: function () { return [{ type: Router }, { type: ActivatedRoute }, { type: undefined, decorators: [{
|
|
@@ -5305,9 +5447,9 @@ class RouterLinkWithHref {
|
|
|
5305
5447
|
});
|
|
5306
5448
|
}
|
|
5307
5449
|
}
|
|
5308
|
-
RouterLinkWithHref.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5309
|
-
RouterLinkWithHref.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5310
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5450
|
+
RouterLinkWithHref.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: RouterLinkWithHref, deps: [{ token: Router }, { token: ActivatedRoute }, { token: i3.LocationStrategy }], target: i0.ɵɵFactoryTarget.Directive });
|
|
5451
|
+
RouterLinkWithHref.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.15", type: RouterLinkWithHref, selector: "a[routerLink],area[routerLink]", inputs: { target: "target", queryParams: "queryParams", fragment: "fragment", queryParamsHandling: "queryParamsHandling", preserveFragment: "preserveFragment", skipLocationChange: "skipLocationChange", replaceUrl: "replaceUrl", state: "state", relativeTo: "relativeTo", routerLink: "routerLink" }, host: { listeners: { "click": "onClick($event.button,$event.ctrlKey,$event.shiftKey,$event.altKey,$event.metaKey)" }, properties: { "attr.target": "this.target", "attr.href": "this.href" } }, usesOnChanges: true, ngImport: i0 });
|
|
5452
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: RouterLinkWithHref, decorators: [{
|
|
5311
5453
|
type: Directive,
|
|
5312
5454
|
args: [{ selector: 'a[routerLink],area[routerLink]' }]
|
|
5313
5455
|
}], ctorParameters: function () { return [{ type: Router }, { type: ActivatedRoute }, { type: i3.LocationStrategy }]; }, propDecorators: { target: [{
|
|
@@ -5404,6 +5546,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.12",
|
|
|
5404
5546
|
* </div>
|
|
5405
5547
|
* ```
|
|
5406
5548
|
*
|
|
5549
|
+
* The `RouterLinkActive` directive can also be used to set the aria-current attribute
|
|
5550
|
+
* to provide an alternative distinction for active elements to visually impaired users.
|
|
5551
|
+
*
|
|
5552
|
+
* For example, the following code adds the 'active' class to the Home Page link when it is
|
|
5553
|
+
* indeed active and in such case also sets its aria-current attribute to 'page':
|
|
5554
|
+
*
|
|
5555
|
+
* ```
|
|
5556
|
+
* <a routerLink="/" routerLinkActive="active" ariaCurrentWhenActive="page">Home Page</a>
|
|
5557
|
+
* ```
|
|
5558
|
+
*
|
|
5407
5559
|
* @ngModule RouterModule
|
|
5408
5560
|
*
|
|
5409
5561
|
* @publicApi
|
|
@@ -5497,6 +5649,12 @@ class RouterLinkActive {
|
|
|
5497
5649
|
this.renderer.removeClass(this.element.nativeElement, c);
|
|
5498
5650
|
}
|
|
5499
5651
|
});
|
|
5652
|
+
if (hasActiveLinks && this.ariaCurrentWhenActive !== undefined) {
|
|
5653
|
+
this.renderer.setAttribute(this.element.nativeElement, 'aria-current', this.ariaCurrentWhenActive.toString());
|
|
5654
|
+
}
|
|
5655
|
+
else {
|
|
5656
|
+
this.renderer.removeAttribute(this.element.nativeElement, 'aria-current');
|
|
5657
|
+
}
|
|
5500
5658
|
// Emit on isActiveChange after classes are updated
|
|
5501
5659
|
this.isActiveChange.emit(hasActiveLinks);
|
|
5502
5660
|
}
|
|
@@ -5516,9 +5674,9 @@ class RouterLinkActive {
|
|
|
5516
5674
|
this.links.some(isActiveCheckFn) || this.linksWithHrefs.some(isActiveCheckFn);
|
|
5517
5675
|
}
|
|
5518
5676
|
}
|
|
5519
|
-
RouterLinkActive.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5520
|
-
RouterLinkActive.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5521
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5677
|
+
RouterLinkActive.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: RouterLinkActive, deps: [{ token: Router }, { token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }, { token: RouterLink, optional: true }, { token: RouterLinkWithHref, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
|
|
5678
|
+
RouterLinkActive.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.15", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: { routerLinkActiveOptions: "routerLinkActiveOptions", ariaCurrentWhenActive: "ariaCurrentWhenActive", routerLinkActive: "routerLinkActive" }, outputs: { isActiveChange: "isActiveChange" }, queries: [{ propertyName: "links", predicate: RouterLink, descendants: true }, { propertyName: "linksWithHrefs", predicate: RouterLinkWithHref, descendants: true }], exportAs: ["routerLinkActive"], usesOnChanges: true, ngImport: i0 });
|
|
5679
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: RouterLinkActive, decorators: [{
|
|
5522
5680
|
type: Directive,
|
|
5523
5681
|
args: [{
|
|
5524
5682
|
selector: '[routerLinkActive]',
|
|
@@ -5536,6 +5694,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.12",
|
|
|
5536
5694
|
args: [RouterLinkWithHref, { descendants: true }]
|
|
5537
5695
|
}], routerLinkActiveOptions: [{
|
|
5538
5696
|
type: Input
|
|
5697
|
+
}], ariaCurrentWhenActive: [{
|
|
5698
|
+
type: Input
|
|
5539
5699
|
}], isActiveChange: [{
|
|
5540
5700
|
type: Output
|
|
5541
5701
|
}], routerLinkActive: [{
|
|
@@ -5619,9 +5779,9 @@ class DefaultTitleStrategy extends TitleStrategy {
|
|
|
5619
5779
|
}
|
|
5620
5780
|
}
|
|
5621
5781
|
}
|
|
5622
|
-
DefaultTitleStrategy.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5623
|
-
DefaultTitleStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5624
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5782
|
+
DefaultTitleStrategy.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: DefaultTitleStrategy, deps: [{ token: i1.Title }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
5783
|
+
DefaultTitleStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: DefaultTitleStrategy, providedIn: 'root' });
|
|
5784
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: DefaultTitleStrategy, decorators: [{
|
|
5625
5785
|
type: Injectable,
|
|
5626
5786
|
args: [{ providedIn: 'root' }]
|
|
5627
5787
|
}], ctorParameters: function () { return [{ type: i1.Title }]; } });
|
|
@@ -5685,13 +5845,11 @@ class NoPreloading {
|
|
|
5685
5845
|
* @publicApi
|
|
5686
5846
|
*/
|
|
5687
5847
|
class RouterPreloader {
|
|
5688
|
-
constructor(router, compiler, injector, preloadingStrategy) {
|
|
5848
|
+
constructor(router, compiler, injector, preloadingStrategy, loader) {
|
|
5689
5849
|
this.router = router;
|
|
5690
5850
|
this.injector = injector;
|
|
5691
5851
|
this.preloadingStrategy = preloadingStrategy;
|
|
5692
|
-
|
|
5693
|
-
const onEndLoad = (r) => router.triggerEvent(new RouteConfigLoadEnd(r));
|
|
5694
|
-
this.loader = new RouterConfigLoader(injector, compiler, onStartLoad, onEndLoad);
|
|
5852
|
+
this.loader = loader;
|
|
5695
5853
|
}
|
|
5696
5854
|
setUpPreloading() {
|
|
5697
5855
|
this.subscription =
|
|
@@ -5700,8 +5858,7 @@ class RouterPreloader {
|
|
|
5700
5858
|
.subscribe(() => { });
|
|
5701
5859
|
}
|
|
5702
5860
|
preload() {
|
|
5703
|
-
|
|
5704
|
-
return this.processRoutes(ngModule, this.router.config);
|
|
5861
|
+
return this.processRoutes(this.injector, this.router.config);
|
|
5705
5862
|
}
|
|
5706
5863
|
/** @nodoc */
|
|
5707
5864
|
ngOnDestroy() {
|
|
@@ -5709,41 +5866,59 @@ class RouterPreloader {
|
|
|
5709
5866
|
this.subscription.unsubscribe();
|
|
5710
5867
|
}
|
|
5711
5868
|
}
|
|
5712
|
-
processRoutes(
|
|
5869
|
+
processRoutes(injector, routes) {
|
|
5713
5870
|
const res = [];
|
|
5714
5871
|
for (const route of routes) {
|
|
5715
|
-
|
|
5716
|
-
|
|
5717
|
-
|
|
5718
|
-
res.push(this.processRoutes(childConfig.module, childConfig.routes));
|
|
5719
|
-
// no config loaded, fetch the config
|
|
5872
|
+
if (route.providers && !route._injector) {
|
|
5873
|
+
route._injector =
|
|
5874
|
+
createEnvironmentInjector(route.providers, injector, `Route: ${route.path}`);
|
|
5720
5875
|
}
|
|
5721
|
-
|
|
5722
|
-
|
|
5723
|
-
|
|
5876
|
+
const injectorForCurrentRoute = route._injector ?? injector;
|
|
5877
|
+
const injectorForChildren = route._loadedInjector ?? injectorForCurrentRoute;
|
|
5878
|
+
if ((route.loadChildren && !route._loadedRoutes) ||
|
|
5879
|
+
(route.loadComponent && !route._loadedComponent)) {
|
|
5880
|
+
res.push(this.preloadConfig(injectorForCurrentRoute, route));
|
|
5724
5881
|
}
|
|
5725
|
-
else if (route.children) {
|
|
5726
|
-
res.push(this.processRoutes(
|
|
5882
|
+
else if (route.children || route._loadedRoutes) {
|
|
5883
|
+
res.push(this.processRoutes(injectorForChildren, (route.children ?? route._loadedRoutes)));
|
|
5727
5884
|
}
|
|
5728
5885
|
}
|
|
5729
|
-
return from(res).pipe(mergeAll()
|
|
5886
|
+
return from(res).pipe(mergeAll());
|
|
5730
5887
|
}
|
|
5731
|
-
preloadConfig(
|
|
5888
|
+
preloadConfig(injector, route) {
|
|
5732
5889
|
return this.preloadingStrategy.preload(route, () => {
|
|
5733
|
-
|
|
5734
|
-
|
|
5735
|
-
|
|
5736
|
-
|
|
5737
|
-
|
|
5890
|
+
let loadedChildren$;
|
|
5891
|
+
if (route.loadChildren && route.canLoad === undefined) {
|
|
5892
|
+
loadedChildren$ = this.loader.loadChildren(injector, route);
|
|
5893
|
+
}
|
|
5894
|
+
else {
|
|
5895
|
+
loadedChildren$ = of(null);
|
|
5896
|
+
}
|
|
5897
|
+
const recursiveLoadChildren$ = loadedChildren$.pipe(mergeMap((config) => {
|
|
5898
|
+
if (config === null) {
|
|
5899
|
+
return of(void 0);
|
|
5900
|
+
}
|
|
5901
|
+
route._loadedRoutes = config.routes;
|
|
5902
|
+
route._loadedInjector = config.injector;
|
|
5903
|
+
// If the loaded config was a module, use that as the module/module injector going
|
|
5904
|
+
// forward. Otherwise, continue using the current module/module injector.
|
|
5905
|
+
return this.processRoutes(config.injector ?? injector, config.routes);
|
|
5738
5906
|
}));
|
|
5907
|
+
if (route.loadComponent && !route._loadedComponent) {
|
|
5908
|
+
const loadComponent$ = this.loader.loadComponent(route);
|
|
5909
|
+
return from([recursiveLoadChildren$, loadComponent$]).pipe(mergeAll());
|
|
5910
|
+
}
|
|
5911
|
+
else {
|
|
5912
|
+
return recursiveLoadChildren$;
|
|
5913
|
+
}
|
|
5739
5914
|
});
|
|
5740
5915
|
}
|
|
5741
5916
|
}
|
|
5742
|
-
RouterPreloader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5743
|
-
RouterPreloader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5744
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5917
|
+
RouterPreloader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: RouterPreloader, deps: [{ token: Router }, { token: i0.Compiler }, { token: i0.EnvironmentInjector }, { token: PreloadingStrategy }, { token: RouterConfigLoader }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
5918
|
+
RouterPreloader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: RouterPreloader });
|
|
5919
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: RouterPreloader, decorators: [{
|
|
5745
5920
|
type: Injectable
|
|
5746
|
-
}], ctorParameters: function () { return [{ type: Router }, { type: i0.Compiler }, { type: i0.
|
|
5921
|
+
}], ctorParameters: function () { return [{ type: Router }, { type: i0.Compiler }, { type: i0.EnvironmentInjector }, { type: PreloadingStrategy }, { type: RouterConfigLoader }]; } });
|
|
5747
5922
|
|
|
5748
5923
|
/**
|
|
5749
5924
|
* @license
|
|
@@ -5827,9 +6002,9 @@ class RouterScroller {
|
|
|
5827
6002
|
}
|
|
5828
6003
|
}
|
|
5829
6004
|
}
|
|
5830
|
-
RouterScroller.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5831
|
-
RouterScroller.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5832
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
6005
|
+
RouterScroller.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: RouterScroller, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
|
|
6006
|
+
RouterScroller.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: RouterScroller });
|
|
6007
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: RouterScroller, decorators: [{
|
|
5833
6008
|
type: Injectable
|
|
5834
6009
|
}], ctorParameters: function () { return [{ type: Router }, { type: i3.ViewportScroller }, { type: undefined }]; } });
|
|
5835
6010
|
|
|
@@ -5872,6 +6047,7 @@ const ROUTER_PROVIDERS = [
|
|
|
5872
6047
|
NoPreloading,
|
|
5873
6048
|
PreloadAllModules,
|
|
5874
6049
|
{ provide: ROUTER_CONFIGURATION, useValue: { enableTracing: false } },
|
|
6050
|
+
RouterConfigLoader,
|
|
5875
6051
|
];
|
|
5876
6052
|
function routerNgProbeToken() {
|
|
5877
6053
|
return new NgProbeToken('Router', Router);
|
|
@@ -5970,10 +6146,10 @@ class RouterModule {
|
|
|
5970
6146
|
return { ngModule: RouterModule, providers: [provideRoutes(routes)] };
|
|
5971
6147
|
}
|
|
5972
6148
|
}
|
|
5973
|
-
RouterModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5974
|
-
RouterModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5975
|
-
RouterModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5976
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
6149
|
+
RouterModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: RouterModule, deps: [{ token: ROUTER_FORROOT_GUARD, optional: true }, { token: Router, optional: true }], target: i0.ɵɵFactoryTarget.NgModule });
|
|
6150
|
+
RouterModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: RouterModule, declarations: [RouterOutlet, RouterLink, RouterLinkWithHref, RouterLinkActive, ɵEmptyOutletComponent], exports: [RouterOutlet, RouterLink, RouterLinkWithHref, RouterLinkActive, ɵEmptyOutletComponent] });
|
|
6151
|
+
RouterModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: RouterModule });
|
|
6152
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: RouterModule, decorators: [{
|
|
5977
6153
|
type: NgModule,
|
|
5978
6154
|
args: [{
|
|
5979
6155
|
declarations: ROUTER_DIRECTIVES,
|
|
@@ -6152,9 +6328,9 @@ class RouterInitializer {
|
|
|
6152
6328
|
this.destroyed = true;
|
|
6153
6329
|
}
|
|
6154
6330
|
}
|
|
6155
|
-
RouterInitializer.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
6156
|
-
RouterInitializer.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
6157
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
6331
|
+
RouterInitializer.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: RouterInitializer, deps: [{ token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
6332
|
+
RouterInitializer.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: RouterInitializer });
|
|
6333
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: RouterInitializer, decorators: [{
|
|
6158
6334
|
type: Injectable
|
|
6159
6335
|
}], ctorParameters: function () { return [{ type: i0.Injector }]; } });
|
|
6160
6336
|
function getAppInitializer(r) {
|
|
@@ -6194,7 +6370,7 @@ function provideRouterInitializer() {
|
|
|
6194
6370
|
/**
|
|
6195
6371
|
* @publicApi
|
|
6196
6372
|
*/
|
|
6197
|
-
const VERSION = new Version('14.0.0-next.
|
|
6373
|
+
const VERSION = new Version('14.0.0-next.15');
|
|
6198
6374
|
|
|
6199
6375
|
/**
|
|
6200
6376
|
* @license
|