@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/fesm2015/router.mjs
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
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
|
*/
|
|
6
6
|
|
|
7
7
|
import * as i0 from '@angular/core';
|
|
8
|
-
import { ɵisObservable, ɵisPromise, EventEmitter, Directive, Attribute, Output, Component,
|
|
8
|
+
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';
|
|
9
9
|
import { from, of, BehaviorSubject, combineLatest, throwError, EmptyError, concat, defer, Observable, EMPTY, ConnectableObservable, Subject } from 'rxjs';
|
|
10
|
-
import { map, switchMap, take, startWith, scan, filter, catchError, concatMap, last as last$1, first, mergeMap, tap, takeLast,
|
|
10
|
+
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';
|
|
11
11
|
import * as i3 from '@angular/common';
|
|
12
12
|
import { Location, LocationStrategy, PlatformLocation, APP_BASE_HREF, ViewportScroller, HashLocationStrategy, PathLocationStrategy, LOCATION_INITIALIZED } from '@angular/common';
|
|
13
13
|
import * as i1 from '@angular/platform-browser';
|
|
@@ -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;
|
|
@@ -1518,7 +1517,7 @@ class ActivatedRouteSnapshot {
|
|
|
1518
1517
|
/** The outlet name of the route */
|
|
1519
1518
|
outlet,
|
|
1520
1519
|
/** The component of the route */
|
|
1521
|
-
component, routeConfig, urlSegment, lastPathIndex, resolve) {
|
|
1520
|
+
component, routeConfig, urlSegment, lastPathIndex, resolve, correctedLastPathIndex) {
|
|
1522
1521
|
this.url = url;
|
|
1523
1522
|
this.params = params;
|
|
1524
1523
|
this.queryParams = queryParams;
|
|
@@ -1529,6 +1528,7 @@ class ActivatedRouteSnapshot {
|
|
|
1529
1528
|
this.routeConfig = routeConfig;
|
|
1530
1529
|
this._urlSegment = urlSegment;
|
|
1531
1530
|
this._lastPathIndex = lastPathIndex;
|
|
1531
|
+
this._correctedLastPathIndex = correctedLastPathIndex !== null && correctedLastPathIndex !== void 0 ? correctedLastPathIndex : lastPathIndex;
|
|
1532
1532
|
this._resolve = resolve;
|
|
1533
1533
|
}
|
|
1534
1534
|
/** The root of the router state */
|
|
@@ -1713,6 +1713,7 @@ function createActivatedRoute(c) {
|
|
|
1713
1713
|
* found in the LICENSE file at https://angular.io/license
|
|
1714
1714
|
*/
|
|
1715
1715
|
function createUrlTree(route, urlTree, commands, queryParams, fragment) {
|
|
1716
|
+
var _a, _b;
|
|
1716
1717
|
if (commands.length === 0) {
|
|
1717
1718
|
return tree(urlTree.root, urlTree.root, urlTree.root, queryParams, fragment);
|
|
1718
1719
|
}
|
|
@@ -1720,11 +1721,27 @@ function createUrlTree(route, urlTree, commands, queryParams, fragment) {
|
|
|
1720
1721
|
if (nav.toRoot()) {
|
|
1721
1722
|
return tree(urlTree.root, urlTree.root, new UrlSegmentGroup([], {}), queryParams, fragment);
|
|
1722
1723
|
}
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1724
|
+
function createTreeUsingPathIndex(lastPathIndex) {
|
|
1725
|
+
var _a;
|
|
1726
|
+
const startingPosition = findStartingPosition(nav, urlTree, (_a = route.snapshot) === null || _a === void 0 ? void 0 : _a._urlSegment, lastPathIndex);
|
|
1727
|
+
const segmentGroup = startingPosition.processChildren ?
|
|
1728
|
+
updateSegmentGroupChildren(startingPosition.segmentGroup, startingPosition.index, nav.commands) :
|
|
1729
|
+
updateSegmentGroup(startingPosition.segmentGroup, startingPosition.index, nav.commands);
|
|
1730
|
+
return tree(urlTree.root, startingPosition.segmentGroup, segmentGroup, queryParams, fragment);
|
|
1731
|
+
}
|
|
1732
|
+
// Note: The types should disallow `snapshot` from being `undefined` but due to test mocks, this
|
|
1733
|
+
// may be the case. Since we try to access it at an earlier point before the refactor to add the
|
|
1734
|
+
// warning for `relativeLinkResolution: 'legacy'`, this may cause failures in tests where it
|
|
1735
|
+
// didn't before.
|
|
1736
|
+
const result = createTreeUsingPathIndex((_a = route.snapshot) === null || _a === void 0 ? void 0 : _a._lastPathIndex);
|
|
1737
|
+
// Check if application is relying on `relativeLinkResolution: 'legacy'`
|
|
1738
|
+
if (typeof ngDevMode === 'undefined' || !!ngDevMode) {
|
|
1739
|
+
const correctedResult = createTreeUsingPathIndex((_b = route.snapshot) === null || _b === void 0 ? void 0 : _b._correctedLastPathIndex);
|
|
1740
|
+
if (correctedResult.toString() !== result.toString()) {
|
|
1741
|
+
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.`);
|
|
1742
|
+
}
|
|
1743
|
+
}
|
|
1744
|
+
return result;
|
|
1728
1745
|
}
|
|
1729
1746
|
function isMatrixParams(command) {
|
|
1730
1747
|
return typeof command === 'object' && command != null && !command.outlets && !command.segmentPath;
|
|
@@ -1829,12 +1846,11 @@ class Position {
|
|
|
1829
1846
|
this.index = index;
|
|
1830
1847
|
}
|
|
1831
1848
|
}
|
|
1832
|
-
function findStartingPosition(nav, tree,
|
|
1849
|
+
function findStartingPosition(nav, tree, segmentGroup, lastPathIndex) {
|
|
1833
1850
|
if (nav.isAbsolute) {
|
|
1834
1851
|
return new Position(tree.root, true, 0);
|
|
1835
1852
|
}
|
|
1836
|
-
if (
|
|
1837
|
-
const segmentGroup = route.snapshot._urlSegment;
|
|
1853
|
+
if (lastPathIndex === -1) {
|
|
1838
1854
|
// Pathless ActivatedRoute has _lastPathIndex === -1 but should not process children
|
|
1839
1855
|
// see issue #26224, #13011, #35687
|
|
1840
1856
|
// However, if the ActivatedRoute is the root we should process children like above.
|
|
@@ -1842,8 +1858,8 @@ function findStartingPosition(nav, tree, route) {
|
|
|
1842
1858
|
return new Position(segmentGroup, processChildren, 0);
|
|
1843
1859
|
}
|
|
1844
1860
|
const modifier = isMatrixParams(nav.commands[0]) ? 0 : 1;
|
|
1845
|
-
const index =
|
|
1846
|
-
return createPositionApplyingDoubleDots(
|
|
1861
|
+
const index = lastPathIndex + modifier;
|
|
1862
|
+
return createPositionApplyingDoubleDots(segmentGroup, index, nav.numberOfDoubleDots);
|
|
1847
1863
|
}
|
|
1848
1864
|
function createPositionApplyingDoubleDots(group, index, numberOfDoubleDots) {
|
|
1849
1865
|
let g = group;
|
|
@@ -2006,181 +2022,76 @@ function compare(path, params, segment) {
|
|
|
2006
2022
|
* Use of this source code is governed by an MIT-style license that can be
|
|
2007
2023
|
* found in the LICENSE file at https://angular.io/license
|
|
2008
2024
|
*/
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
class
|
|
2015
|
-
constructor(
|
|
2016
|
-
this.
|
|
2017
|
-
this.
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
this.
|
|
2025
|
-
|
|
2026
|
-
this.activateChildRoutes(futureRoot, currRoot, parentContexts);
|
|
2027
|
-
}
|
|
2028
|
-
// De-activate the child route that are not re-used for the future state
|
|
2029
|
-
deactivateChildRoutes(futureNode, currNode, contexts) {
|
|
2030
|
-
const children = nodeChildrenAsMap(currNode);
|
|
2031
|
-
// Recurse on the routes active in the future state to de-activate deeper children
|
|
2032
|
-
futureNode.children.forEach(futureChild => {
|
|
2033
|
-
const childOutletName = futureChild.value.outlet;
|
|
2034
|
-
this.deactivateRoutes(futureChild, children[childOutletName], contexts);
|
|
2035
|
-
delete children[childOutletName];
|
|
2036
|
-
});
|
|
2037
|
-
// De-activate the routes that will not be re-used
|
|
2038
|
-
forEach(children, (v, childName) => {
|
|
2039
|
-
this.deactivateRouteAndItsChildren(v, contexts);
|
|
2040
|
-
});
|
|
2041
|
-
}
|
|
2042
|
-
deactivateRoutes(futureNode, currNode, parentContext) {
|
|
2043
|
-
const future = futureNode.value;
|
|
2044
|
-
const curr = currNode ? currNode.value : null;
|
|
2045
|
-
if (future === curr) {
|
|
2046
|
-
// Reusing the node, check to see if the children need to be de-activated
|
|
2047
|
-
if (future.component) {
|
|
2048
|
-
// If we have a normal route, we need to go through an outlet.
|
|
2049
|
-
const context = parentContext.getContext(future.outlet);
|
|
2050
|
-
if (context) {
|
|
2051
|
-
this.deactivateChildRoutes(futureNode, currNode, context.children);
|
|
2052
|
-
}
|
|
2053
|
-
}
|
|
2054
|
-
else {
|
|
2055
|
-
// if we have a componentless route, we recurse but keep the same outlet map.
|
|
2056
|
-
this.deactivateChildRoutes(futureNode, currNode, parentContext);
|
|
2057
|
-
}
|
|
2058
|
-
}
|
|
2059
|
-
else {
|
|
2060
|
-
if (curr) {
|
|
2061
|
-
// Deactivate the current route which will not be re-used
|
|
2062
|
-
this.deactivateRouteAndItsChildren(currNode, parentContext);
|
|
2063
|
-
}
|
|
2064
|
-
}
|
|
2025
|
+
/**
|
|
2026
|
+
* Store contextual information about a `RouterOutlet`
|
|
2027
|
+
*
|
|
2028
|
+
* @publicApi
|
|
2029
|
+
*/
|
|
2030
|
+
class OutletContext {
|
|
2031
|
+
constructor() {
|
|
2032
|
+
this.outlet = null;
|
|
2033
|
+
this.route = null;
|
|
2034
|
+
/**
|
|
2035
|
+
* @deprecated Passing a resolver to retrieve a component factory is not required and is
|
|
2036
|
+
* deprecated since v14.
|
|
2037
|
+
*/
|
|
2038
|
+
this.resolver = null;
|
|
2039
|
+
this.injector = null;
|
|
2040
|
+
this.children = new ChildrenOutletContexts();
|
|
2041
|
+
this.attachRef = null;
|
|
2065
2042
|
}
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2043
|
+
}
|
|
2044
|
+
/**
|
|
2045
|
+
* Store contextual information about the children (= nested) `RouterOutlet`
|
|
2046
|
+
*
|
|
2047
|
+
* @publicApi
|
|
2048
|
+
*/
|
|
2049
|
+
class ChildrenOutletContexts {
|
|
2050
|
+
constructor() {
|
|
2051
|
+
// contexts for child outlets, by name.
|
|
2052
|
+
this.contexts = new Map();
|
|
2075
2053
|
}
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
const
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
this.deactivateRouteAndItsChildren(children[childOutlet], contexts);
|
|
2082
|
-
}
|
|
2083
|
-
if (context && context.outlet) {
|
|
2084
|
-
const componentRef = context.outlet.detach();
|
|
2085
|
-
const contexts = context.children.onOutletDeactivated();
|
|
2086
|
-
this.routeReuseStrategy.store(route.value.snapshot, { componentRef, route, contexts });
|
|
2087
|
-
}
|
|
2054
|
+
/** Called when a `RouterOutlet` directive is instantiated */
|
|
2055
|
+
onChildOutletCreated(childName, outlet) {
|
|
2056
|
+
const context = this.getOrCreateContext(childName);
|
|
2057
|
+
context.outlet = outlet;
|
|
2058
|
+
this.contexts.set(childName, context);
|
|
2088
2059
|
}
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
if (context && context.outlet) {
|
|
2099
|
-
// Destroy the component
|
|
2100
|
-
context.outlet.deactivate();
|
|
2101
|
-
// Destroy the contexts for all the outlets that were in the component
|
|
2102
|
-
context.children.onOutletDeactivated();
|
|
2103
|
-
// Clear the information about the attached component on the context but keep the reference to
|
|
2104
|
-
// the outlet.
|
|
2060
|
+
/**
|
|
2061
|
+
* Called when a `RouterOutlet` directive is destroyed.
|
|
2062
|
+
* We need to keep the context as the outlet could be destroyed inside a NgIf and might be
|
|
2063
|
+
* re-created later.
|
|
2064
|
+
*/
|
|
2065
|
+
onChildOutletDestroyed(childName) {
|
|
2066
|
+
const context = this.getContext(childName);
|
|
2067
|
+
if (context) {
|
|
2068
|
+
context.outlet = null;
|
|
2105
2069
|
context.attachRef = null;
|
|
2106
|
-
context.resolver = null;
|
|
2107
|
-
context.route = null;
|
|
2108
2070
|
}
|
|
2109
2071
|
}
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
}
|
|
2072
|
+
/**
|
|
2073
|
+
* Called when the corresponding route is deactivated during navigation.
|
|
2074
|
+
* Because the component get destroyed, all children outlet are destroyed.
|
|
2075
|
+
*/
|
|
2076
|
+
onOutletDeactivated() {
|
|
2077
|
+
const contexts = this.contexts;
|
|
2078
|
+
this.contexts = new Map();
|
|
2079
|
+
return contexts;
|
|
2119
2080
|
}
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
if (
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
const context = parentContexts.getOrCreateContext(future.outlet);
|
|
2129
|
-
this.activateChildRoutes(futureNode, currNode, context.children);
|
|
2130
|
-
}
|
|
2131
|
-
else {
|
|
2132
|
-
// if we have a componentless route, we recurse but keep the same outlet map.
|
|
2133
|
-
this.activateChildRoutes(futureNode, currNode, parentContexts);
|
|
2134
|
-
}
|
|
2135
|
-
}
|
|
2136
|
-
else {
|
|
2137
|
-
if (future.component) {
|
|
2138
|
-
// if we have a normal route, we need to place the component into the outlet and recurse.
|
|
2139
|
-
const context = parentContexts.getOrCreateContext(future.outlet);
|
|
2140
|
-
if (this.routeReuseStrategy.shouldAttach(future.snapshot)) {
|
|
2141
|
-
const stored = this.routeReuseStrategy.retrieve(future.snapshot);
|
|
2142
|
-
this.routeReuseStrategy.store(future.snapshot, null);
|
|
2143
|
-
context.children.onOutletReAttached(stored.contexts);
|
|
2144
|
-
context.attachRef = stored.componentRef;
|
|
2145
|
-
context.route = stored.route.value;
|
|
2146
|
-
if (context.outlet) {
|
|
2147
|
-
// Attach right away when the outlet has already been instantiated
|
|
2148
|
-
// Otherwise attach from `RouterOutlet.ngOnInit` when it is instantiated
|
|
2149
|
-
context.outlet.attach(stored.componentRef, stored.route.value);
|
|
2150
|
-
}
|
|
2151
|
-
advanceActivatedRoute(stored.route.value);
|
|
2152
|
-
this.activateChildRoutes(futureNode, null, context.children);
|
|
2153
|
-
}
|
|
2154
|
-
else {
|
|
2155
|
-
const config = parentLoadedConfig(future.snapshot);
|
|
2156
|
-
const cmpFactoryResolver = config ? config.module.componentFactoryResolver : null;
|
|
2157
|
-
context.attachRef = null;
|
|
2158
|
-
context.route = future;
|
|
2159
|
-
context.resolver = cmpFactoryResolver;
|
|
2160
|
-
if (context.outlet) {
|
|
2161
|
-
// Activate the outlet when it has already been instantiated
|
|
2162
|
-
// Otherwise it will get activated from its `ngOnInit` when instantiated
|
|
2163
|
-
context.outlet.activateWith(future, cmpFactoryResolver);
|
|
2164
|
-
}
|
|
2165
|
-
this.activateChildRoutes(futureNode, null, context.children);
|
|
2166
|
-
}
|
|
2167
|
-
}
|
|
2168
|
-
else {
|
|
2169
|
-
// if we have a componentless route, we recurse but keep the same outlet map.
|
|
2170
|
-
this.activateChildRoutes(futureNode, null, parentContexts);
|
|
2171
|
-
}
|
|
2081
|
+
onOutletReAttached(contexts) {
|
|
2082
|
+
this.contexts = contexts;
|
|
2083
|
+
}
|
|
2084
|
+
getOrCreateContext(childName) {
|
|
2085
|
+
let context = this.getContext(childName);
|
|
2086
|
+
if (!context) {
|
|
2087
|
+
context = new OutletContext();
|
|
2088
|
+
this.contexts.set(childName, context);
|
|
2172
2089
|
}
|
|
2090
|
+
return context;
|
|
2173
2091
|
}
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
for (let s = snapshot.parent; s; s = s.parent) {
|
|
2177
|
-
const route = s.routeConfig;
|
|
2178
|
-
if (route && route._loadedConfig)
|
|
2179
|
-
return route._loadedConfig;
|
|
2180
|
-
if (route && route.component)
|
|
2181
|
-
return null;
|
|
2092
|
+
getContext(childName) {
|
|
2093
|
+
return this.contexts.get(childName) || null;
|
|
2182
2094
|
}
|
|
2183
|
-
return null;
|
|
2184
2095
|
}
|
|
2185
2096
|
|
|
2186
2097
|
/**
|
|
@@ -2190,182 +2101,13 @@ function parentLoadedConfig(snapshot) {
|
|
|
2190
2101
|
* Use of this source code is governed by an MIT-style license that can be
|
|
2191
2102
|
* found in the LICENSE file at https://angular.io/license
|
|
2192
2103
|
*/
|
|
2193
|
-
class LoadedRouterConfig {
|
|
2194
|
-
constructor(routes, module) {
|
|
2195
|
-
this.routes = routes;
|
|
2196
|
-
this.module = module;
|
|
2197
|
-
}
|
|
2198
|
-
}
|
|
2199
|
-
|
|
2200
2104
|
/**
|
|
2201
|
-
* @
|
|
2202
|
-
* Copyright Google LLC All Rights Reserved.
|
|
2105
|
+
* @description
|
|
2203
2106
|
*
|
|
2204
|
-
*
|
|
2205
|
-
* found in the LICENSE file at https://angular.io/license
|
|
2206
|
-
*/
|
|
2207
|
-
/**
|
|
2208
|
-
* Simple function check, but generic so type inference will flow. Example:
|
|
2107
|
+
* Acts as a placeholder that Angular dynamically fills based on the current router state.
|
|
2209
2108
|
*
|
|
2210
|
-
*
|
|
2211
|
-
*
|
|
2212
|
-
* }
|
|
2213
|
-
*
|
|
2214
|
-
* if (isFunction<product>(fn)) {
|
|
2215
|
-
* return fn(1, 2);
|
|
2216
|
-
* } else {
|
|
2217
|
-
* throw "Must provide the `product` function";
|
|
2218
|
-
* }
|
|
2219
|
-
*/
|
|
2220
|
-
function isFunction(v) {
|
|
2221
|
-
return typeof v === 'function';
|
|
2222
|
-
}
|
|
2223
|
-
function isBoolean(v) {
|
|
2224
|
-
return typeof v === 'boolean';
|
|
2225
|
-
}
|
|
2226
|
-
function isUrlTree(v) {
|
|
2227
|
-
return v instanceof UrlTree;
|
|
2228
|
-
}
|
|
2229
|
-
function isCanLoad(guard) {
|
|
2230
|
-
return guard && isFunction(guard.canLoad);
|
|
2231
|
-
}
|
|
2232
|
-
function isCanActivate(guard) {
|
|
2233
|
-
return guard && isFunction(guard.canActivate);
|
|
2234
|
-
}
|
|
2235
|
-
function isCanActivateChild(guard) {
|
|
2236
|
-
return guard && isFunction(guard.canActivateChild);
|
|
2237
|
-
}
|
|
2238
|
-
function isCanDeactivate(guard) {
|
|
2239
|
-
return guard && isFunction(guard.canDeactivate);
|
|
2240
|
-
}
|
|
2241
|
-
|
|
2242
|
-
/**
|
|
2243
|
-
* @license
|
|
2244
|
-
* Copyright Google LLC All Rights Reserved.
|
|
2245
|
-
*
|
|
2246
|
-
* Use of this source code is governed by an MIT-style license that can be
|
|
2247
|
-
* found in the LICENSE file at https://angular.io/license
|
|
2248
|
-
*/
|
|
2249
|
-
const INITIAL_VALUE = Symbol('INITIAL_VALUE');
|
|
2250
|
-
function prioritizedGuardValue() {
|
|
2251
|
-
return switchMap(obs => {
|
|
2252
|
-
return combineLatest(obs.map(o => o.pipe(take(1), startWith(INITIAL_VALUE))))
|
|
2253
|
-
.pipe(scan((acc, list) => {
|
|
2254
|
-
let isPending = false;
|
|
2255
|
-
return list.reduce((innerAcc, val, i) => {
|
|
2256
|
-
if (innerAcc !== INITIAL_VALUE)
|
|
2257
|
-
return innerAcc;
|
|
2258
|
-
// Toggle pending flag if any values haven't been set yet
|
|
2259
|
-
if (val === INITIAL_VALUE)
|
|
2260
|
-
isPending = true;
|
|
2261
|
-
// Any other return values are only valid if we haven't yet hit a pending
|
|
2262
|
-
// call. This guarantees that in the case of a guard at the bottom of the
|
|
2263
|
-
// tree that returns a redirect, we will wait for the higher priority
|
|
2264
|
-
// guard at the top to finish before performing the redirect.
|
|
2265
|
-
if (!isPending) {
|
|
2266
|
-
// Early return when we hit a `false` value as that should always
|
|
2267
|
-
// cancel navigation
|
|
2268
|
-
if (val === false)
|
|
2269
|
-
return val;
|
|
2270
|
-
if (i === list.length - 1 || isUrlTree(val)) {
|
|
2271
|
-
return val;
|
|
2272
|
-
}
|
|
2273
|
-
}
|
|
2274
|
-
return innerAcc;
|
|
2275
|
-
}, acc);
|
|
2276
|
-
}, INITIAL_VALUE), filter(item => item !== INITIAL_VALUE), map(item => isUrlTree(item) ? item : item === true), //
|
|
2277
|
-
take(1));
|
|
2278
|
-
});
|
|
2279
|
-
}
|
|
2280
|
-
|
|
2281
|
-
/**
|
|
2282
|
-
* @license
|
|
2283
|
-
* Copyright Google LLC All Rights Reserved.
|
|
2284
|
-
*
|
|
2285
|
-
* Use of this source code is governed by an MIT-style license that can be
|
|
2286
|
-
* found in the LICENSE file at https://angular.io/license
|
|
2287
|
-
*/
|
|
2288
|
-
/**
|
|
2289
|
-
* Store contextual information about a `RouterOutlet`
|
|
2290
|
-
*
|
|
2291
|
-
* @publicApi
|
|
2292
|
-
*/
|
|
2293
|
-
class OutletContext {
|
|
2294
|
-
constructor() {
|
|
2295
|
-
this.outlet = null;
|
|
2296
|
-
this.route = null;
|
|
2297
|
-
this.resolver = null;
|
|
2298
|
-
this.children = new ChildrenOutletContexts();
|
|
2299
|
-
this.attachRef = null;
|
|
2300
|
-
}
|
|
2301
|
-
}
|
|
2302
|
-
/**
|
|
2303
|
-
* Store contextual information about the children (= nested) `RouterOutlet`
|
|
2304
|
-
*
|
|
2305
|
-
* @publicApi
|
|
2306
|
-
*/
|
|
2307
|
-
class ChildrenOutletContexts {
|
|
2308
|
-
constructor() {
|
|
2309
|
-
// contexts for child outlets, by name.
|
|
2310
|
-
this.contexts = new Map();
|
|
2311
|
-
}
|
|
2312
|
-
/** Called when a `RouterOutlet` directive is instantiated */
|
|
2313
|
-
onChildOutletCreated(childName, outlet) {
|
|
2314
|
-
const context = this.getOrCreateContext(childName);
|
|
2315
|
-
context.outlet = outlet;
|
|
2316
|
-
this.contexts.set(childName, context);
|
|
2317
|
-
}
|
|
2318
|
-
/**
|
|
2319
|
-
* Called when a `RouterOutlet` directive is destroyed.
|
|
2320
|
-
* We need to keep the context as the outlet could be destroyed inside a NgIf and might be
|
|
2321
|
-
* re-created later.
|
|
2322
|
-
*/
|
|
2323
|
-
onChildOutletDestroyed(childName) {
|
|
2324
|
-
const context = this.getContext(childName);
|
|
2325
|
-
if (context) {
|
|
2326
|
-
context.outlet = null;
|
|
2327
|
-
context.attachRef = null;
|
|
2328
|
-
}
|
|
2329
|
-
}
|
|
2330
|
-
/**
|
|
2331
|
-
* Called when the corresponding route is deactivated during navigation.
|
|
2332
|
-
* Because the component get destroyed, all children outlet are destroyed.
|
|
2333
|
-
*/
|
|
2334
|
-
onOutletDeactivated() {
|
|
2335
|
-
const contexts = this.contexts;
|
|
2336
|
-
this.contexts = new Map();
|
|
2337
|
-
return contexts;
|
|
2338
|
-
}
|
|
2339
|
-
onOutletReAttached(contexts) {
|
|
2340
|
-
this.contexts = contexts;
|
|
2341
|
-
}
|
|
2342
|
-
getOrCreateContext(childName) {
|
|
2343
|
-
let context = this.getContext(childName);
|
|
2344
|
-
if (!context) {
|
|
2345
|
-
context = new OutletContext();
|
|
2346
|
-
this.contexts.set(childName, context);
|
|
2347
|
-
}
|
|
2348
|
-
return context;
|
|
2349
|
-
}
|
|
2350
|
-
getContext(childName) {
|
|
2351
|
-
return this.contexts.get(childName) || null;
|
|
2352
|
-
}
|
|
2353
|
-
}
|
|
2354
|
-
|
|
2355
|
-
/**
|
|
2356
|
-
* @license
|
|
2357
|
-
* Copyright Google LLC All Rights Reserved.
|
|
2358
|
-
*
|
|
2359
|
-
* Use of this source code is governed by an MIT-style license that can be
|
|
2360
|
-
* found in the LICENSE file at https://angular.io/license
|
|
2361
|
-
*/
|
|
2362
|
-
/**
|
|
2363
|
-
* @description
|
|
2364
|
-
*
|
|
2365
|
-
* Acts as a placeholder that Angular dynamically fills based on the current router state.
|
|
2366
|
-
*
|
|
2367
|
-
* Each outlet can have a unique name, determined by the optional `name` attribute.
|
|
2368
|
-
* The name cannot be set or changed dynamically. If not set, default value is "primary".
|
|
2109
|
+
* Each outlet can have a unique name, determined by the optional `name` attribute.
|
|
2110
|
+
* The name cannot be set or changed dynamically. If not set, default value is "primary".
|
|
2369
2111
|
*
|
|
2370
2112
|
* ```
|
|
2371
2113
|
* <router-outlet></router-outlet>
|
|
@@ -2411,11 +2153,11 @@ class ChildrenOutletContexts {
|
|
|
2411
2153
|
* @publicApi
|
|
2412
2154
|
*/
|
|
2413
2155
|
class RouterOutlet {
|
|
2414
|
-
constructor(parentContexts, location,
|
|
2156
|
+
constructor(parentContexts, location, name, changeDetector, environmentInjector) {
|
|
2415
2157
|
this.parentContexts = parentContexts;
|
|
2416
2158
|
this.location = location;
|
|
2417
|
-
this.resolver = resolver;
|
|
2418
2159
|
this.changeDetector = changeDetector;
|
|
2160
|
+
this.environmentInjector = environmentInjector;
|
|
2419
2161
|
this.activated = null;
|
|
2420
2162
|
this._activatedRoute = null;
|
|
2421
2163
|
this.activateEvents = new EventEmitter();
|
|
@@ -2450,7 +2192,7 @@ class RouterOutlet {
|
|
|
2450
2192
|
}
|
|
2451
2193
|
else {
|
|
2452
2194
|
// otherwise the component defined in the configuration is created
|
|
2453
|
-
this.activateWith(context.route, context.
|
|
2195
|
+
this.activateWith(context.route, context.injector);
|
|
2454
2196
|
}
|
|
2455
2197
|
}
|
|
2456
2198
|
}
|
|
@@ -2509,34 +2251,40 @@ class RouterOutlet {
|
|
|
2509
2251
|
this.deactivateEvents.emit(c);
|
|
2510
2252
|
}
|
|
2511
2253
|
}
|
|
2512
|
-
activateWith(activatedRoute,
|
|
2254
|
+
activateWith(activatedRoute, resolverOrInjector) {
|
|
2513
2255
|
if (this.isActivated) {
|
|
2514
2256
|
throw new Error('Cannot activate an already activated outlet');
|
|
2515
2257
|
}
|
|
2516
2258
|
this._activatedRoute = activatedRoute;
|
|
2259
|
+
const location = this.location;
|
|
2517
2260
|
const snapshot = activatedRoute._futureSnapshot;
|
|
2518
|
-
const component = snapshot.
|
|
2519
|
-
resolver = resolver || this.resolver;
|
|
2520
|
-
const factory = resolver.resolveComponentFactory(component);
|
|
2261
|
+
const component = snapshot.component;
|
|
2521
2262
|
const childContexts = this.parentContexts.getOrCreateContext(this.name).children;
|
|
2522
|
-
const injector = new OutletInjector(activatedRoute, childContexts,
|
|
2523
|
-
|
|
2263
|
+
const injector = new OutletInjector(activatedRoute, childContexts, location.injector);
|
|
2264
|
+
if (resolverOrInjector && isComponentFactoryResolver(resolverOrInjector)) {
|
|
2265
|
+
const factory = resolverOrInjector.resolveComponentFactory(component);
|
|
2266
|
+
this.activated = location.createComponent(factory, location.length, injector);
|
|
2267
|
+
}
|
|
2268
|
+
else {
|
|
2269
|
+
const environmentInjector = resolverOrInjector !== null && resolverOrInjector !== void 0 ? resolverOrInjector : this.environmentInjector;
|
|
2270
|
+
this.activated = location.createComponent(component, { index: location.length, injector, environmentInjector });
|
|
2271
|
+
}
|
|
2524
2272
|
// Calling `markForCheck` to make sure we will run the change detection when the
|
|
2525
2273
|
// `RouterOutlet` is inside a `ChangeDetectionStrategy.OnPush` component.
|
|
2526
2274
|
this.changeDetector.markForCheck();
|
|
2527
2275
|
this.activateEvents.emit(this.activated.instance);
|
|
2528
2276
|
}
|
|
2529
2277
|
}
|
|
2530
|
-
RouterOutlet.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
2531
|
-
RouterOutlet.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
2532
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
2278
|
+
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 });
|
|
2279
|
+
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 });
|
|
2280
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: RouterOutlet, decorators: [{
|
|
2533
2281
|
type: Directive,
|
|
2534
2282
|
args: [{ selector: 'router-outlet', exportAs: 'outlet' }]
|
|
2535
2283
|
}], ctorParameters: function () {
|
|
2536
|
-
return [{ type: ChildrenOutletContexts }, { type: i0.ViewContainerRef }, { type:
|
|
2284
|
+
return [{ type: ChildrenOutletContexts }, { type: i0.ViewContainerRef }, { type: undefined, decorators: [{
|
|
2537
2285
|
type: Attribute,
|
|
2538
2286
|
args: ['name']
|
|
2539
|
-
}] }, { type: i0.ChangeDetectorRef }];
|
|
2287
|
+
}] }, { type: i0.ChangeDetectorRef }, { type: i0.EnvironmentInjector }];
|
|
2540
2288
|
}, propDecorators: { activateEvents: [{
|
|
2541
2289
|
type: Output,
|
|
2542
2290
|
args: ['activate']
|
|
@@ -2563,7 +2311,387 @@ class OutletInjector {
|
|
|
2563
2311
|
if (token === ChildrenOutletContexts) {
|
|
2564
2312
|
return this.childContexts;
|
|
2565
2313
|
}
|
|
2566
|
-
return this.parent.get(token, notFoundValue);
|
|
2314
|
+
return this.parent.get(token, notFoundValue);
|
|
2315
|
+
}
|
|
2316
|
+
}
|
|
2317
|
+
function isComponentFactoryResolver(item) {
|
|
2318
|
+
return !!item.resolveComponentFactory;
|
|
2319
|
+
}
|
|
2320
|
+
|
|
2321
|
+
/**
|
|
2322
|
+
* @license
|
|
2323
|
+
* Copyright Google LLC All Rights Reserved.
|
|
2324
|
+
*
|
|
2325
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
2326
|
+
* found in the LICENSE file at https://angular.io/license
|
|
2327
|
+
*/
|
|
2328
|
+
/**
|
|
2329
|
+
* This component is used internally within the router to be a placeholder when an empty
|
|
2330
|
+
* router-outlet is needed. For example, with a config such as:
|
|
2331
|
+
*
|
|
2332
|
+
* `{path: 'parent', outlet: 'nav', children: [...]}`
|
|
2333
|
+
*
|
|
2334
|
+
* In order to render, there needs to be a component on this config, which will default
|
|
2335
|
+
* to this `EmptyOutletComponent`.
|
|
2336
|
+
*/
|
|
2337
|
+
class ɵEmptyOutletComponent {
|
|
2338
|
+
}
|
|
2339
|
+
ɵEmptyOutletComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: ɵEmptyOutletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2340
|
+
ɵ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"] }] });
|
|
2341
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: ɵEmptyOutletComponent, decorators: [{
|
|
2342
|
+
type: Component,
|
|
2343
|
+
args: [{ template: `<router-outlet></router-outlet>` }]
|
|
2344
|
+
}] });
|
|
2345
|
+
|
|
2346
|
+
/**
|
|
2347
|
+
* @license
|
|
2348
|
+
* Copyright Google LLC All Rights Reserved.
|
|
2349
|
+
*
|
|
2350
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
2351
|
+
* found in the LICENSE file at https://angular.io/license
|
|
2352
|
+
*/
|
|
2353
|
+
function getLoadedRoutes(route) {
|
|
2354
|
+
return route._loadedRoutes;
|
|
2355
|
+
}
|
|
2356
|
+
function getLoadedInjector(route) {
|
|
2357
|
+
return route._loadedInjector;
|
|
2358
|
+
}
|
|
2359
|
+
function getLoadedComponent(route) {
|
|
2360
|
+
return route._loadedComponent;
|
|
2361
|
+
}
|
|
2362
|
+
function getProvidersInjector(route) {
|
|
2363
|
+
return route._injector;
|
|
2364
|
+
}
|
|
2365
|
+
function validateConfig(config, parentPath = '', requireStandaloneComponents = false) {
|
|
2366
|
+
// forEach doesn't iterate undefined values
|
|
2367
|
+
for (let i = 0; i < config.length; i++) {
|
|
2368
|
+
const route = config[i];
|
|
2369
|
+
const fullPath = getFullPath(parentPath, route);
|
|
2370
|
+
validateNode(route, fullPath, requireStandaloneComponents);
|
|
2371
|
+
}
|
|
2372
|
+
}
|
|
2373
|
+
function assertStandalone(fullPath, component) {
|
|
2374
|
+
if (component && !ɵisStandalone(component)) {
|
|
2375
|
+
throw new Error(`Invalid configuration of route '${fullPath}'. The component must be standalone.`);
|
|
2376
|
+
}
|
|
2377
|
+
}
|
|
2378
|
+
function validateNode(route, fullPath, requireStandaloneComponents) {
|
|
2379
|
+
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
2380
|
+
if (!route) {
|
|
2381
|
+
throw new Error(`
|
|
2382
|
+
Invalid configuration of route '${fullPath}': Encountered undefined route.
|
|
2383
|
+
The reason might be an extra comma.
|
|
2384
|
+
|
|
2385
|
+
Example:
|
|
2386
|
+
const routes: Routes = [
|
|
2387
|
+
{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },
|
|
2388
|
+
{ path: 'dashboard', component: DashboardComponent },, << two commas
|
|
2389
|
+
{ path: 'detail/:id', component: HeroDetailComponent }
|
|
2390
|
+
];
|
|
2391
|
+
`);
|
|
2392
|
+
}
|
|
2393
|
+
if (Array.isArray(route)) {
|
|
2394
|
+
throw new Error(`Invalid configuration of route '${fullPath}': Array cannot be specified`);
|
|
2395
|
+
}
|
|
2396
|
+
if (!route.component && !route.loadComponent && !route.children && !route.loadChildren &&
|
|
2397
|
+
(route.outlet && route.outlet !== PRIMARY_OUTLET)) {
|
|
2398
|
+
throw new Error(`Invalid configuration of route '${fullPath}': a componentless route without children or loadChildren cannot have a named outlet set`);
|
|
2399
|
+
}
|
|
2400
|
+
if (route.redirectTo && route.children) {
|
|
2401
|
+
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and children cannot be used together`);
|
|
2402
|
+
}
|
|
2403
|
+
if (route.redirectTo && route.loadChildren) {
|
|
2404
|
+
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and loadChildren cannot be used together`);
|
|
2405
|
+
}
|
|
2406
|
+
if (route.children && route.loadChildren) {
|
|
2407
|
+
throw new Error(`Invalid configuration of route '${fullPath}': children and loadChildren cannot be used together`);
|
|
2408
|
+
}
|
|
2409
|
+
if (route.redirectTo && (route.component || route.loadComponent)) {
|
|
2410
|
+
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and component/loadComponent cannot be used together`);
|
|
2411
|
+
}
|
|
2412
|
+
if (route.component && route.loadComponent) {
|
|
2413
|
+
throw new Error(`Invalid configuration of route '${fullPath}': component and loadComponent cannot be used together`);
|
|
2414
|
+
}
|
|
2415
|
+
if (route.redirectTo && route.canActivate) {
|
|
2416
|
+
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and canActivate cannot be used together. Redirects happen before activation ` +
|
|
2417
|
+
`so canActivate will never be executed.`);
|
|
2418
|
+
}
|
|
2419
|
+
if (route.path && route.matcher) {
|
|
2420
|
+
throw new Error(`Invalid configuration of route '${fullPath}': path and matcher cannot be used together`);
|
|
2421
|
+
}
|
|
2422
|
+
if (route.redirectTo === void 0 && !route.component && !route.loadComponent &&
|
|
2423
|
+
!route.children && !route.loadChildren) {
|
|
2424
|
+
throw new Error(`Invalid configuration of route '${fullPath}'. One of the following must be provided: component, loadComponent, redirectTo, children or loadChildren`);
|
|
2425
|
+
}
|
|
2426
|
+
if (route.path === void 0 && route.matcher === void 0) {
|
|
2427
|
+
throw new Error(`Invalid configuration of route '${fullPath}': routes must have either a path or a matcher specified`);
|
|
2428
|
+
}
|
|
2429
|
+
if (typeof route.path === 'string' && route.path.charAt(0) === '/') {
|
|
2430
|
+
throw new Error(`Invalid configuration of route '${fullPath}': path cannot start with a slash`);
|
|
2431
|
+
}
|
|
2432
|
+
if (route.path === '' && route.redirectTo !== void 0 && route.pathMatch === void 0) {
|
|
2433
|
+
const exp = `The default value of 'pathMatch' is 'prefix', but often the intent is to use 'full'.`;
|
|
2434
|
+
throw new Error(`Invalid configuration of route '{path: "${fullPath}", redirectTo: "${route.redirectTo}"}': please provide 'pathMatch'. ${exp}`);
|
|
2435
|
+
}
|
|
2436
|
+
if (requireStandaloneComponents) {
|
|
2437
|
+
assertStandalone(fullPath, route.component);
|
|
2438
|
+
}
|
|
2439
|
+
}
|
|
2440
|
+
if (route.children) {
|
|
2441
|
+
validateConfig(route.children, fullPath, requireStandaloneComponents);
|
|
2442
|
+
}
|
|
2443
|
+
}
|
|
2444
|
+
function getFullPath(parentPath, currentRoute) {
|
|
2445
|
+
if (!currentRoute) {
|
|
2446
|
+
return parentPath;
|
|
2447
|
+
}
|
|
2448
|
+
if (!parentPath && !currentRoute.path) {
|
|
2449
|
+
return '';
|
|
2450
|
+
}
|
|
2451
|
+
else if (parentPath && !currentRoute.path) {
|
|
2452
|
+
return `${parentPath}/`;
|
|
2453
|
+
}
|
|
2454
|
+
else if (!parentPath && currentRoute.path) {
|
|
2455
|
+
return currentRoute.path;
|
|
2456
|
+
}
|
|
2457
|
+
else {
|
|
2458
|
+
return `${parentPath}/${currentRoute.path}`;
|
|
2459
|
+
}
|
|
2460
|
+
}
|
|
2461
|
+
/**
|
|
2462
|
+
* Makes a copy of the config and adds any default required properties.
|
|
2463
|
+
*/
|
|
2464
|
+
function standardizeConfig(r) {
|
|
2465
|
+
const children = r.children && r.children.map(standardizeConfig);
|
|
2466
|
+
const c = children ? Object.assign(Object.assign({}, r), { children }) : Object.assign({}, r);
|
|
2467
|
+
if ((!c.component && !c.loadComponent) && (children || c.loadChildren) &&
|
|
2468
|
+
(c.outlet && c.outlet !== PRIMARY_OUTLET)) {
|
|
2469
|
+
c.component = ɵEmptyOutletComponent;
|
|
2470
|
+
}
|
|
2471
|
+
return c;
|
|
2472
|
+
}
|
|
2473
|
+
/** Returns the `route.outlet` or PRIMARY_OUTLET if none exists. */
|
|
2474
|
+
function getOutlet(route) {
|
|
2475
|
+
return route.outlet || PRIMARY_OUTLET;
|
|
2476
|
+
}
|
|
2477
|
+
/**
|
|
2478
|
+
* Sorts the `routes` such that the ones with an outlet matching `outletName` come first.
|
|
2479
|
+
* The order of the configs is otherwise preserved.
|
|
2480
|
+
*/
|
|
2481
|
+
function sortByMatchingOutlets(routes, outletName) {
|
|
2482
|
+
const sortedConfig = routes.filter(r => getOutlet(r) === outletName);
|
|
2483
|
+
sortedConfig.push(...routes.filter(r => getOutlet(r) !== outletName));
|
|
2484
|
+
return sortedConfig;
|
|
2485
|
+
}
|
|
2486
|
+
/**
|
|
2487
|
+
* Gets the first injector in the snapshot's parent tree.
|
|
2488
|
+
*
|
|
2489
|
+
* If the `Route` has a static list of providers, the returned injector will be the one created from
|
|
2490
|
+
* those. If it does not exist, the returned injector may come from the parents, which may be from a
|
|
2491
|
+
* loaded config or their static providers.
|
|
2492
|
+
*
|
|
2493
|
+
* Returns `null` if there is neither this nor any parents have a stored injector.
|
|
2494
|
+
*
|
|
2495
|
+
* Generally used for retrieving the injector to use for getting tokens for guards/resolvers and
|
|
2496
|
+
* also used for getting the correct injector to use for creating components.
|
|
2497
|
+
*/
|
|
2498
|
+
function getClosestRouteInjector(snapshot) {
|
|
2499
|
+
var _a;
|
|
2500
|
+
if (!snapshot)
|
|
2501
|
+
return null;
|
|
2502
|
+
// If the current route has its own injector, which is created from the static providers on the
|
|
2503
|
+
// route itself, we should use that. Otherwise, we start at the parent since we do not want to
|
|
2504
|
+
// include the lazy loaded injector from this route.
|
|
2505
|
+
if ((_a = snapshot.routeConfig) === null || _a === void 0 ? void 0 : _a._injector) {
|
|
2506
|
+
return snapshot.routeConfig._injector;
|
|
2507
|
+
}
|
|
2508
|
+
for (let s = snapshot.parent; s; s = s.parent) {
|
|
2509
|
+
const route = s.routeConfig;
|
|
2510
|
+
// Note that the order here is important. `_loadedInjector` stored on the route with
|
|
2511
|
+
// `loadChildren: () => NgModule` so it applies to child routes with priority. The `_injector`
|
|
2512
|
+
// is created from the static providers on that parent route, so it applies to the children as
|
|
2513
|
+
// well, but only if there is no lazy loaded NgModuleRef injector.
|
|
2514
|
+
if (route === null || route === void 0 ? void 0 : route._loadedInjector)
|
|
2515
|
+
return route._loadedInjector;
|
|
2516
|
+
if (route === null || route === void 0 ? void 0 : route._injector)
|
|
2517
|
+
return route._injector;
|
|
2518
|
+
}
|
|
2519
|
+
return null;
|
|
2520
|
+
}
|
|
2521
|
+
|
|
2522
|
+
/**
|
|
2523
|
+
* @license
|
|
2524
|
+
* Copyright Google LLC All Rights Reserved.
|
|
2525
|
+
*
|
|
2526
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
2527
|
+
* found in the LICENSE file at https://angular.io/license
|
|
2528
|
+
*/
|
|
2529
|
+
const activateRoutes = (rootContexts, routeReuseStrategy, forwardEvent) => map(t => {
|
|
2530
|
+
new ActivateRoutes(routeReuseStrategy, t.targetRouterState, t.currentRouterState, forwardEvent)
|
|
2531
|
+
.activate(rootContexts);
|
|
2532
|
+
return t;
|
|
2533
|
+
});
|
|
2534
|
+
class ActivateRoutes {
|
|
2535
|
+
constructor(routeReuseStrategy, futureState, currState, forwardEvent) {
|
|
2536
|
+
this.routeReuseStrategy = routeReuseStrategy;
|
|
2537
|
+
this.futureState = futureState;
|
|
2538
|
+
this.currState = currState;
|
|
2539
|
+
this.forwardEvent = forwardEvent;
|
|
2540
|
+
}
|
|
2541
|
+
activate(parentContexts) {
|
|
2542
|
+
const futureRoot = this.futureState._root;
|
|
2543
|
+
const currRoot = this.currState ? this.currState._root : null;
|
|
2544
|
+
this.deactivateChildRoutes(futureRoot, currRoot, parentContexts);
|
|
2545
|
+
advanceActivatedRoute(this.futureState.root);
|
|
2546
|
+
this.activateChildRoutes(futureRoot, currRoot, parentContexts);
|
|
2547
|
+
}
|
|
2548
|
+
// De-activate the child route that are not re-used for the future state
|
|
2549
|
+
deactivateChildRoutes(futureNode, currNode, contexts) {
|
|
2550
|
+
const children = nodeChildrenAsMap(currNode);
|
|
2551
|
+
// Recurse on the routes active in the future state to de-activate deeper children
|
|
2552
|
+
futureNode.children.forEach(futureChild => {
|
|
2553
|
+
const childOutletName = futureChild.value.outlet;
|
|
2554
|
+
this.deactivateRoutes(futureChild, children[childOutletName], contexts);
|
|
2555
|
+
delete children[childOutletName];
|
|
2556
|
+
});
|
|
2557
|
+
// De-activate the routes that will not be re-used
|
|
2558
|
+
forEach(children, (v, childName) => {
|
|
2559
|
+
this.deactivateRouteAndItsChildren(v, contexts);
|
|
2560
|
+
});
|
|
2561
|
+
}
|
|
2562
|
+
deactivateRoutes(futureNode, currNode, parentContext) {
|
|
2563
|
+
const future = futureNode.value;
|
|
2564
|
+
const curr = currNode ? currNode.value : null;
|
|
2565
|
+
if (future === curr) {
|
|
2566
|
+
// Reusing the node, check to see if the children need to be de-activated
|
|
2567
|
+
if (future.component) {
|
|
2568
|
+
// If we have a normal route, we need to go through an outlet.
|
|
2569
|
+
const context = parentContext.getContext(future.outlet);
|
|
2570
|
+
if (context) {
|
|
2571
|
+
this.deactivateChildRoutes(futureNode, currNode, context.children);
|
|
2572
|
+
}
|
|
2573
|
+
}
|
|
2574
|
+
else {
|
|
2575
|
+
// if we have a componentless route, we recurse but keep the same outlet map.
|
|
2576
|
+
this.deactivateChildRoutes(futureNode, currNode, parentContext);
|
|
2577
|
+
}
|
|
2578
|
+
}
|
|
2579
|
+
else {
|
|
2580
|
+
if (curr) {
|
|
2581
|
+
// Deactivate the current route which will not be re-used
|
|
2582
|
+
this.deactivateRouteAndItsChildren(currNode, parentContext);
|
|
2583
|
+
}
|
|
2584
|
+
}
|
|
2585
|
+
}
|
|
2586
|
+
deactivateRouteAndItsChildren(route, parentContexts) {
|
|
2587
|
+
// If there is no component, the Route is never attached to an outlet (because there is no
|
|
2588
|
+
// component to attach).
|
|
2589
|
+
if (route.value.component && this.routeReuseStrategy.shouldDetach(route.value.snapshot)) {
|
|
2590
|
+
this.detachAndStoreRouteSubtree(route, parentContexts);
|
|
2591
|
+
}
|
|
2592
|
+
else {
|
|
2593
|
+
this.deactivateRouteAndOutlet(route, parentContexts);
|
|
2594
|
+
}
|
|
2595
|
+
}
|
|
2596
|
+
detachAndStoreRouteSubtree(route, parentContexts) {
|
|
2597
|
+
const context = parentContexts.getContext(route.value.outlet);
|
|
2598
|
+
const contexts = context && route.value.component ? context.children : parentContexts;
|
|
2599
|
+
const children = nodeChildrenAsMap(route);
|
|
2600
|
+
for (const childOutlet of Object.keys(children)) {
|
|
2601
|
+
this.deactivateRouteAndItsChildren(children[childOutlet], contexts);
|
|
2602
|
+
}
|
|
2603
|
+
if (context && context.outlet) {
|
|
2604
|
+
const componentRef = context.outlet.detach();
|
|
2605
|
+
const contexts = context.children.onOutletDeactivated();
|
|
2606
|
+
this.routeReuseStrategy.store(route.value.snapshot, { componentRef, route, contexts });
|
|
2607
|
+
}
|
|
2608
|
+
}
|
|
2609
|
+
deactivateRouteAndOutlet(route, parentContexts) {
|
|
2610
|
+
const context = parentContexts.getContext(route.value.outlet);
|
|
2611
|
+
// The context could be `null` if we are on a componentless route but there may still be
|
|
2612
|
+
// children that need deactivating.
|
|
2613
|
+
const contexts = context && route.value.component ? context.children : parentContexts;
|
|
2614
|
+
const children = nodeChildrenAsMap(route);
|
|
2615
|
+
for (const childOutlet of Object.keys(children)) {
|
|
2616
|
+
this.deactivateRouteAndItsChildren(children[childOutlet], contexts);
|
|
2617
|
+
}
|
|
2618
|
+
if (context && context.outlet) {
|
|
2619
|
+
// Destroy the component
|
|
2620
|
+
context.outlet.deactivate();
|
|
2621
|
+
// Destroy the contexts for all the outlets that were in the component
|
|
2622
|
+
context.children.onOutletDeactivated();
|
|
2623
|
+
// Clear the information about the attached component on the context but keep the reference to
|
|
2624
|
+
// the outlet.
|
|
2625
|
+
context.attachRef = null;
|
|
2626
|
+
context.resolver = null;
|
|
2627
|
+
context.route = null;
|
|
2628
|
+
}
|
|
2629
|
+
}
|
|
2630
|
+
activateChildRoutes(futureNode, currNode, contexts) {
|
|
2631
|
+
const children = nodeChildrenAsMap(currNode);
|
|
2632
|
+
futureNode.children.forEach(c => {
|
|
2633
|
+
this.activateRoutes(c, children[c.value.outlet], contexts);
|
|
2634
|
+
this.forwardEvent(new ActivationEnd(c.value.snapshot));
|
|
2635
|
+
});
|
|
2636
|
+
if (futureNode.children.length) {
|
|
2637
|
+
this.forwardEvent(new ChildActivationEnd(futureNode.value.snapshot));
|
|
2638
|
+
}
|
|
2639
|
+
}
|
|
2640
|
+
activateRoutes(futureNode, currNode, parentContexts) {
|
|
2641
|
+
var _a;
|
|
2642
|
+
const future = futureNode.value;
|
|
2643
|
+
const curr = currNode ? currNode.value : null;
|
|
2644
|
+
advanceActivatedRoute(future);
|
|
2645
|
+
// reusing the node
|
|
2646
|
+
if (future === curr) {
|
|
2647
|
+
if (future.component) {
|
|
2648
|
+
// If we have a normal route, we need to go through an outlet.
|
|
2649
|
+
const context = parentContexts.getOrCreateContext(future.outlet);
|
|
2650
|
+
this.activateChildRoutes(futureNode, currNode, context.children);
|
|
2651
|
+
}
|
|
2652
|
+
else {
|
|
2653
|
+
// if we have a componentless route, we recurse but keep the same outlet map.
|
|
2654
|
+
this.activateChildRoutes(futureNode, currNode, parentContexts);
|
|
2655
|
+
}
|
|
2656
|
+
}
|
|
2657
|
+
else {
|
|
2658
|
+
if (future.component) {
|
|
2659
|
+
// if we have a normal route, we need to place the component into the outlet and recurse.
|
|
2660
|
+
const context = parentContexts.getOrCreateContext(future.outlet);
|
|
2661
|
+
if (this.routeReuseStrategy.shouldAttach(future.snapshot)) {
|
|
2662
|
+
const stored = this.routeReuseStrategy.retrieve(future.snapshot);
|
|
2663
|
+
this.routeReuseStrategy.store(future.snapshot, null);
|
|
2664
|
+
context.children.onOutletReAttached(stored.contexts);
|
|
2665
|
+
context.attachRef = stored.componentRef;
|
|
2666
|
+
context.route = stored.route.value;
|
|
2667
|
+
if (context.outlet) {
|
|
2668
|
+
// Attach right away when the outlet has already been instantiated
|
|
2669
|
+
// Otherwise attach from `RouterOutlet.ngOnInit` when it is instantiated
|
|
2670
|
+
context.outlet.attach(stored.componentRef, stored.route.value);
|
|
2671
|
+
}
|
|
2672
|
+
advanceActivatedRoute(stored.route.value);
|
|
2673
|
+
this.activateChildRoutes(futureNode, null, context.children);
|
|
2674
|
+
}
|
|
2675
|
+
else {
|
|
2676
|
+
const injector = getClosestRouteInjector(future.snapshot);
|
|
2677
|
+
const cmpFactoryResolver = (_a = injector === null || injector === void 0 ? void 0 : injector.get(ComponentFactoryResolver)) !== null && _a !== void 0 ? _a : null;
|
|
2678
|
+
context.attachRef = null;
|
|
2679
|
+
context.route = future;
|
|
2680
|
+
context.resolver = cmpFactoryResolver;
|
|
2681
|
+
context.injector = injector;
|
|
2682
|
+
if (context.outlet) {
|
|
2683
|
+
// Activate the outlet when it has already been instantiated
|
|
2684
|
+
// Otherwise it will get activated from its `ngOnInit` when instantiated
|
|
2685
|
+
context.outlet.activateWith(future, context.injector);
|
|
2686
|
+
}
|
|
2687
|
+
this.activateChildRoutes(futureNode, null, context.children);
|
|
2688
|
+
}
|
|
2689
|
+
}
|
|
2690
|
+
else {
|
|
2691
|
+
// if we have a componentless route, we recurse but keep the same outlet map.
|
|
2692
|
+
this.activateChildRoutes(futureNode, null, parentContexts);
|
|
2693
|
+
}
|
|
2694
|
+
}
|
|
2567
2695
|
}
|
|
2568
2696
|
}
|
|
2569
2697
|
|
|
@@ -2575,22 +2703,39 @@ class OutletInjector {
|
|
|
2575
2703
|
* found in the LICENSE file at https://angular.io/license
|
|
2576
2704
|
*/
|
|
2577
2705
|
/**
|
|
2578
|
-
*
|
|
2579
|
-
* router-outlet is needed. For example, with a config such as:
|
|
2706
|
+
* Simple function check, but generic so type inference will flow. Example:
|
|
2580
2707
|
*
|
|
2581
|
-
*
|
|
2708
|
+
* function product(a: number, b: number) {
|
|
2709
|
+
* return a * b;
|
|
2710
|
+
* }
|
|
2582
2711
|
*
|
|
2583
|
-
*
|
|
2584
|
-
*
|
|
2712
|
+
* if (isFunction<product>(fn)) {
|
|
2713
|
+
* return fn(1, 2);
|
|
2714
|
+
* } else {
|
|
2715
|
+
* throw "Must provide the `product` function";
|
|
2716
|
+
* }
|
|
2585
2717
|
*/
|
|
2586
|
-
|
|
2718
|
+
function isFunction(v) {
|
|
2719
|
+
return typeof v === 'function';
|
|
2720
|
+
}
|
|
2721
|
+
function isBoolean(v) {
|
|
2722
|
+
return typeof v === 'boolean';
|
|
2723
|
+
}
|
|
2724
|
+
function isUrlTree(v) {
|
|
2725
|
+
return v instanceof UrlTree;
|
|
2726
|
+
}
|
|
2727
|
+
function isCanLoad(guard) {
|
|
2728
|
+
return guard && isFunction(guard.canLoad);
|
|
2729
|
+
}
|
|
2730
|
+
function isCanActivate(guard) {
|
|
2731
|
+
return guard && isFunction(guard.canActivate);
|
|
2732
|
+
}
|
|
2733
|
+
function isCanActivateChild(guard) {
|
|
2734
|
+
return guard && isFunction(guard.canActivateChild);
|
|
2735
|
+
}
|
|
2736
|
+
function isCanDeactivate(guard) {
|
|
2737
|
+
return guard && isFunction(guard.canDeactivate);
|
|
2587
2738
|
}
|
|
2588
|
-
ɵEmptyOutletComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.12", ngImport: i0, type: ɵEmptyOutletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2589
|
-
ɵ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"] }] });
|
|
2590
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.12", ngImport: i0, type: ɵEmptyOutletComponent, decorators: [{
|
|
2591
|
-
type: Component,
|
|
2592
|
-
args: [{ template: `<router-outlet></router-outlet>` }]
|
|
2593
|
-
}] });
|
|
2594
2739
|
|
|
2595
2740
|
/**
|
|
2596
2741
|
* @license
|
|
@@ -2599,113 +2744,36 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.12",
|
|
|
2599
2744
|
* Use of this source code is governed by an MIT-style license that can be
|
|
2600
2745
|
* found in the LICENSE file at https://angular.io/license
|
|
2601
2746
|
*/
|
|
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
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
if (route.redirectTo && route.children) {
|
|
2633
|
-
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and children cannot be used together`);
|
|
2634
|
-
}
|
|
2635
|
-
if (route.redirectTo && route.loadChildren) {
|
|
2636
|
-
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and loadChildren cannot be used together`);
|
|
2637
|
-
}
|
|
2638
|
-
if (route.children && route.loadChildren) {
|
|
2639
|
-
throw new Error(`Invalid configuration of route '${fullPath}': children and loadChildren cannot be used together`);
|
|
2640
|
-
}
|
|
2641
|
-
if (route.redirectTo && route.component) {
|
|
2642
|
-
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and component cannot be used together`);
|
|
2643
|
-
}
|
|
2644
|
-
if (route.redirectTo && route.canActivate) {
|
|
2645
|
-
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and canActivate cannot be used together. Redirects happen before activation ` +
|
|
2646
|
-
`so canActivate will never be executed.`);
|
|
2647
|
-
}
|
|
2648
|
-
if (route.path && route.matcher) {
|
|
2649
|
-
throw new Error(`Invalid configuration of route '${fullPath}': path and matcher cannot be used together`);
|
|
2650
|
-
}
|
|
2651
|
-
if (route.redirectTo === void 0 && !route.component && !route.children && !route.loadChildren) {
|
|
2652
|
-
throw new Error(`Invalid configuration of route '${fullPath}'. One of the following must be provided: component, redirectTo, children or loadChildren`);
|
|
2653
|
-
}
|
|
2654
|
-
if (route.path === void 0 && route.matcher === void 0) {
|
|
2655
|
-
throw new Error(`Invalid configuration of route '${fullPath}': routes must have either a path or a matcher specified`);
|
|
2656
|
-
}
|
|
2657
|
-
if (typeof route.path === 'string' && route.path.charAt(0) === '/') {
|
|
2658
|
-
throw new Error(`Invalid configuration of route '${fullPath}': path cannot start with a slash`);
|
|
2659
|
-
}
|
|
2660
|
-
if (route.path === '' && route.redirectTo !== void 0 && route.pathMatch === void 0) {
|
|
2661
|
-
const exp = `The default value of 'pathMatch' is 'prefix', but often the intent is to use 'full'.`;
|
|
2662
|
-
throw new Error(`Invalid configuration of route '{path: "${fullPath}", redirectTo: "${route.redirectTo}"}': please provide 'pathMatch'. ${exp}`);
|
|
2663
|
-
}
|
|
2664
|
-
}
|
|
2665
|
-
if (route.children) {
|
|
2666
|
-
validateConfig(route.children, fullPath);
|
|
2667
|
-
}
|
|
2668
|
-
}
|
|
2669
|
-
function getFullPath(parentPath, currentRoute) {
|
|
2670
|
-
if (!currentRoute) {
|
|
2671
|
-
return parentPath;
|
|
2672
|
-
}
|
|
2673
|
-
if (!parentPath && !currentRoute.path) {
|
|
2674
|
-
return '';
|
|
2675
|
-
}
|
|
2676
|
-
else if (parentPath && !currentRoute.path) {
|
|
2677
|
-
return `${parentPath}/`;
|
|
2678
|
-
}
|
|
2679
|
-
else if (!parentPath && currentRoute.path) {
|
|
2680
|
-
return currentRoute.path;
|
|
2681
|
-
}
|
|
2682
|
-
else {
|
|
2683
|
-
return `${parentPath}/${currentRoute.path}`;
|
|
2684
|
-
}
|
|
2685
|
-
}
|
|
2686
|
-
/**
|
|
2687
|
-
* Makes a copy of the config and adds any default required properties.
|
|
2688
|
-
*/
|
|
2689
|
-
function standardizeConfig(r) {
|
|
2690
|
-
const children = r.children && r.children.map(standardizeConfig);
|
|
2691
|
-
const c = children ? Object.assign(Object.assign({}, r), { children }) : Object.assign({}, r);
|
|
2692
|
-
if (!c.component && (children || c.loadChildren) && (c.outlet && c.outlet !== PRIMARY_OUTLET)) {
|
|
2693
|
-
c.component = ɵEmptyOutletComponent;
|
|
2694
|
-
}
|
|
2695
|
-
return c;
|
|
2696
|
-
}
|
|
2697
|
-
/** Returns the `route.outlet` or PRIMARY_OUTLET if none exists. */
|
|
2698
|
-
function getOutlet(route) {
|
|
2699
|
-
return route.outlet || PRIMARY_OUTLET;
|
|
2700
|
-
}
|
|
2701
|
-
/**
|
|
2702
|
-
* Sorts the `routes` such that the ones with an outlet matching `outletName` come first.
|
|
2703
|
-
* The order of the configs is otherwise preserved.
|
|
2704
|
-
*/
|
|
2705
|
-
function sortByMatchingOutlets(routes, outletName) {
|
|
2706
|
-
const sortedConfig = routes.filter(r => getOutlet(r) === outletName);
|
|
2707
|
-
sortedConfig.push(...routes.filter(r => getOutlet(r) !== outletName));
|
|
2708
|
-
return sortedConfig;
|
|
2747
|
+
const INITIAL_VALUE = Symbol('INITIAL_VALUE');
|
|
2748
|
+
function prioritizedGuardValue() {
|
|
2749
|
+
return switchMap(obs => {
|
|
2750
|
+
return combineLatest(obs.map(o => o.pipe(take(1), startWith(INITIAL_VALUE))))
|
|
2751
|
+
.pipe(scan((acc, list) => {
|
|
2752
|
+
let isPending = false;
|
|
2753
|
+
return list.reduce((innerAcc, val, i) => {
|
|
2754
|
+
if (innerAcc !== INITIAL_VALUE)
|
|
2755
|
+
return innerAcc;
|
|
2756
|
+
// Toggle pending flag if any values haven't been set yet
|
|
2757
|
+
if (val === INITIAL_VALUE)
|
|
2758
|
+
isPending = true;
|
|
2759
|
+
// Any other return values are only valid if we haven't yet hit a pending
|
|
2760
|
+
// call. This guarantees that in the case of a guard at the bottom of the
|
|
2761
|
+
// tree that returns a redirect, we will wait for the higher priority
|
|
2762
|
+
// guard at the top to finish before performing the redirect.
|
|
2763
|
+
if (!isPending) {
|
|
2764
|
+
// Early return when we hit a `false` value as that should always
|
|
2765
|
+
// cancel navigation
|
|
2766
|
+
if (val === false)
|
|
2767
|
+
return val;
|
|
2768
|
+
if (i === list.length - 1 || isUrlTree(val)) {
|
|
2769
|
+
return val;
|
|
2770
|
+
}
|
|
2771
|
+
}
|
|
2772
|
+
return innerAcc;
|
|
2773
|
+
}, acc);
|
|
2774
|
+
}, INITIAL_VALUE), filter(item => item !== INITIAL_VALUE), map(item => isUrlTree(item) ? item : item === true), //
|
|
2775
|
+
take(1));
|
|
2776
|
+
});
|
|
2709
2777
|
}
|
|
2710
2778
|
|
|
2711
2779
|
/**
|
|
@@ -2783,6 +2851,9 @@ function addEmptyPathsToChildrenIfNeeded(segmentGroup, consumedSegments, slicedS
|
|
|
2783
2851
|
s._sourceSegment = segmentGroup;
|
|
2784
2852
|
if (relativeLinkResolution === 'legacy') {
|
|
2785
2853
|
s._segmentIndexShift = segmentGroup.segments.length;
|
|
2854
|
+
if (typeof ngDevMode === 'undefined' || !!ngDevMode) {
|
|
2855
|
+
s._segmentIndexShiftCorrected = consumedSegments.length;
|
|
2856
|
+
}
|
|
2786
2857
|
}
|
|
2787
2858
|
else {
|
|
2788
2859
|
s._segmentIndexShift = consumedSegments.length;
|
|
@@ -2883,17 +2954,17 @@ function canLoadFails(route) {
|
|
|
2883
2954
|
*
|
|
2884
2955
|
* Lazy modules are loaded along the way.
|
|
2885
2956
|
*/
|
|
2886
|
-
function applyRedirects$1(
|
|
2887
|
-
return new ApplyRedirects(
|
|
2957
|
+
function applyRedirects$1(injector, configLoader, urlSerializer, urlTree, config) {
|
|
2958
|
+
return new ApplyRedirects(injector, configLoader, urlSerializer, urlTree, config).apply();
|
|
2888
2959
|
}
|
|
2889
2960
|
class ApplyRedirects {
|
|
2890
|
-
constructor(
|
|
2961
|
+
constructor(injector, configLoader, urlSerializer, urlTree, config) {
|
|
2962
|
+
this.injector = injector;
|
|
2891
2963
|
this.configLoader = configLoader;
|
|
2892
2964
|
this.urlSerializer = urlSerializer;
|
|
2893
2965
|
this.urlTree = urlTree;
|
|
2894
2966
|
this.config = config;
|
|
2895
2967
|
this.allowRedirects = true;
|
|
2896
|
-
this.ngModule = moduleInjector.get(NgModuleRef);
|
|
2897
2968
|
}
|
|
2898
2969
|
apply() {
|
|
2899
2970
|
const splitGroup = split(this.urlTree.root, [], [], this.config).segmentGroup;
|
|
@@ -2904,7 +2975,7 @@ class ApplyRedirects {
|
|
|
2904
2975
|
// them. We should be able to remove this logic as a "breaking change" but should do some more
|
|
2905
2976
|
// investigation into the failures first.
|
|
2906
2977
|
const rootSegmentGroup = new UrlSegmentGroup(splitGroup.segments, splitGroup.children);
|
|
2907
|
-
const expanded$ = this.expandSegmentGroup(this.
|
|
2978
|
+
const expanded$ = this.expandSegmentGroup(this.injector, this.config, rootSegmentGroup, PRIMARY_OUTLET);
|
|
2908
2979
|
const urlTrees$ = expanded$.pipe(map((rootSegmentGroup) => {
|
|
2909
2980
|
return this.createUrlTree(squashSegmentGroup(rootSegmentGroup), this.urlTree.queryParams, this.urlTree.fragment);
|
|
2910
2981
|
}));
|
|
@@ -2923,7 +2994,7 @@ class ApplyRedirects {
|
|
|
2923
2994
|
}));
|
|
2924
2995
|
}
|
|
2925
2996
|
match(tree) {
|
|
2926
|
-
const expanded$ = this.expandSegmentGroup(this.
|
|
2997
|
+
const expanded$ = this.expandSegmentGroup(this.injector, this.config, tree.root, PRIMARY_OUTLET);
|
|
2927
2998
|
const mapped$ = expanded$.pipe(map((rootSegmentGroup) => {
|
|
2928
2999
|
return this.createUrlTree(squashSegmentGroup(rootSegmentGroup), tree.queryParams, tree.fragment);
|
|
2929
3000
|
}));
|
|
@@ -2943,15 +3014,15 @@ class ApplyRedirects {
|
|
|
2943
3014
|
rootCandidate;
|
|
2944
3015
|
return new UrlTree(root, queryParams, fragment);
|
|
2945
3016
|
}
|
|
2946
|
-
expandSegmentGroup(
|
|
3017
|
+
expandSegmentGroup(injector, routes, segmentGroup, outlet) {
|
|
2947
3018
|
if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) {
|
|
2948
|
-
return this.expandChildren(
|
|
3019
|
+
return this.expandChildren(injector, routes, segmentGroup)
|
|
2949
3020
|
.pipe(map((children) => new UrlSegmentGroup([], children)));
|
|
2950
3021
|
}
|
|
2951
|
-
return this.expandSegment(
|
|
3022
|
+
return this.expandSegment(injector, segmentGroup, routes, segmentGroup.segments, outlet, true);
|
|
2952
3023
|
}
|
|
2953
3024
|
// Recursively expand segment groups for all the child outlets
|
|
2954
|
-
expandChildren(
|
|
3025
|
+
expandChildren(injector, routes, segmentGroup) {
|
|
2955
3026
|
// Expand outlets one at a time, starting with the primary outlet. We need to do it this way
|
|
2956
3027
|
// because an absolute redirect from the primary outlet takes precedence.
|
|
2957
3028
|
const childOutlets = [];
|
|
@@ -2970,16 +3041,26 @@ class ApplyRedirects {
|
|
|
2970
3041
|
// first, followed by routes for other outlets, which might match if they have an
|
|
2971
3042
|
// empty path.
|
|
2972
3043
|
const sortedRoutes = sortByMatchingOutlets(routes, childOutlet);
|
|
2973
|
-
return this.expandSegmentGroup(
|
|
3044
|
+
return this.expandSegmentGroup(injector, sortedRoutes, child, childOutlet)
|
|
2974
3045
|
.pipe(map(s => ({ segment: s, outlet: childOutlet })));
|
|
2975
3046
|
}), scan((children, expandedChild) => {
|
|
2976
3047
|
children[expandedChild.outlet] = expandedChild.segment;
|
|
2977
3048
|
return children;
|
|
2978
3049
|
}, {}), last$1());
|
|
2979
3050
|
}
|
|
2980
|
-
expandSegment(
|
|
2981
|
-
return from(routes).pipe(concatMap(
|
|
2982
|
-
|
|
3051
|
+
expandSegment(injector, segmentGroup, routes, segments, outlet, allowRedirects) {
|
|
3052
|
+
return from(routes).pipe(concatMap(r => {
|
|
3053
|
+
var _a;
|
|
3054
|
+
if (r.providers && !r._injector) {
|
|
3055
|
+
r._injector = createEnvironmentInjector(r.providers, injector, `Route: ${r.path}`);
|
|
3056
|
+
}
|
|
3057
|
+
// We specifically _do not_ want to include the _loadedInjector here. The loaded injector
|
|
3058
|
+
// only applies to the route's children, not the route itself. Note that this distinction
|
|
3059
|
+
// only applies here to any tokens we try to retrieve during this phase. At the moment,
|
|
3060
|
+
// that only includes `canLoad`, which won't run again once the child module is loaded. As
|
|
3061
|
+
// a result, this makes no difference right now, but could in the future if there are more
|
|
3062
|
+
// actions here that need DI (for example, a canMatch guard).
|
|
3063
|
+
const expanded$ = this.expandSegmentAgainstRoute((_a = r._injector) !== null && _a !== void 0 ? _a : injector, segmentGroup, routes, r, segments, outlet, allowRedirects);
|
|
2983
3064
|
return expanded$.pipe(catchError((e) => {
|
|
2984
3065
|
if (e instanceof NoMatch$1) {
|
|
2985
3066
|
return of(null);
|
|
@@ -2996,35 +3077,35 @@ class ApplyRedirects {
|
|
|
2996
3077
|
throw e;
|
|
2997
3078
|
}));
|
|
2998
3079
|
}
|
|
2999
|
-
expandSegmentAgainstRoute(
|
|
3080
|
+
expandSegmentAgainstRoute(injector, segmentGroup, routes, route, paths, outlet, allowRedirects) {
|
|
3000
3081
|
if (!isImmediateMatch(route, segmentGroup, paths, outlet)) {
|
|
3001
3082
|
return noMatch(segmentGroup);
|
|
3002
3083
|
}
|
|
3003
3084
|
if (route.redirectTo === undefined) {
|
|
3004
|
-
return this.matchSegmentAgainstRoute(
|
|
3085
|
+
return this.matchSegmentAgainstRoute(injector, segmentGroup, route, paths, outlet);
|
|
3005
3086
|
}
|
|
3006
3087
|
if (allowRedirects && this.allowRedirects) {
|
|
3007
|
-
return this.expandSegmentAgainstRouteUsingRedirect(
|
|
3088
|
+
return this.expandSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, paths, outlet);
|
|
3008
3089
|
}
|
|
3009
3090
|
return noMatch(segmentGroup);
|
|
3010
3091
|
}
|
|
3011
|
-
expandSegmentAgainstRouteUsingRedirect(
|
|
3092
|
+
expandSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet) {
|
|
3012
3093
|
if (route.path === '**') {
|
|
3013
|
-
return this.expandWildCardWithParamsAgainstRouteUsingRedirect(
|
|
3094
|
+
return this.expandWildCardWithParamsAgainstRouteUsingRedirect(injector, routes, route, outlet);
|
|
3014
3095
|
}
|
|
3015
|
-
return this.expandRegularSegmentAgainstRouteUsingRedirect(
|
|
3096
|
+
return this.expandRegularSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet);
|
|
3016
3097
|
}
|
|
3017
|
-
expandWildCardWithParamsAgainstRouteUsingRedirect(
|
|
3098
|
+
expandWildCardWithParamsAgainstRouteUsingRedirect(injector, routes, route, outlet) {
|
|
3018
3099
|
const newTree = this.applyRedirectCommands([], route.redirectTo, {});
|
|
3019
3100
|
if (route.redirectTo.startsWith('/')) {
|
|
3020
3101
|
return absoluteRedirect(newTree);
|
|
3021
3102
|
}
|
|
3022
3103
|
return this.lineralizeSegments(route, newTree).pipe(mergeMap((newSegments) => {
|
|
3023
3104
|
const group = new UrlSegmentGroup(newSegments, {});
|
|
3024
|
-
return this.expandSegment(
|
|
3105
|
+
return this.expandSegment(injector, group, routes, newSegments, outlet, false);
|
|
3025
3106
|
}));
|
|
3026
3107
|
}
|
|
3027
|
-
expandRegularSegmentAgainstRouteUsingRedirect(
|
|
3108
|
+
expandRegularSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet) {
|
|
3028
3109
|
const { matched, consumedSegments, remainingSegments, positionalParamSegments } = match(segmentGroup, route, segments);
|
|
3029
3110
|
if (!matched)
|
|
3030
3111
|
return noMatch(segmentGroup);
|
|
@@ -3033,16 +3114,18 @@ class ApplyRedirects {
|
|
|
3033
3114
|
return absoluteRedirect(newTree);
|
|
3034
3115
|
}
|
|
3035
3116
|
return this.lineralizeSegments(route, newTree).pipe(mergeMap((newSegments) => {
|
|
3036
|
-
return this.expandSegment(
|
|
3117
|
+
return this.expandSegment(injector, segmentGroup, routes, newSegments.concat(remainingSegments), outlet, false);
|
|
3037
3118
|
}));
|
|
3038
3119
|
}
|
|
3039
|
-
matchSegmentAgainstRoute(
|
|
3120
|
+
matchSegmentAgainstRoute(injector, rawSegmentGroup, route, segments, outlet) {
|
|
3040
3121
|
if (route.path === '**') {
|
|
3041
3122
|
if (route.loadChildren) {
|
|
3042
|
-
const loaded$ = route.
|
|
3043
|
-
|
|
3123
|
+
const loaded$ = route._loadedRoutes ?
|
|
3124
|
+
of({ routes: route._loadedRoutes, injector: route._loadedInjector }) :
|
|
3125
|
+
this.configLoader.loadChildren(injector, route);
|
|
3044
3126
|
return loaded$.pipe(map((cfg) => {
|
|
3045
|
-
route.
|
|
3127
|
+
route._loadedRoutes = cfg.routes;
|
|
3128
|
+
route._loadedInjector = cfg.injector;
|
|
3046
3129
|
return new UrlSegmentGroup(segments, {});
|
|
3047
3130
|
}));
|
|
3048
3131
|
}
|
|
@@ -3051,55 +3134,56 @@ class ApplyRedirects {
|
|
|
3051
3134
|
const { matched, consumedSegments, remainingSegments } = match(rawSegmentGroup, route, segments);
|
|
3052
3135
|
if (!matched)
|
|
3053
3136
|
return noMatch(rawSegmentGroup);
|
|
3054
|
-
const childConfig$ = this.getChildConfig(
|
|
3137
|
+
const childConfig$ = this.getChildConfig(injector, route, segments);
|
|
3055
3138
|
return childConfig$.pipe(mergeMap((routerConfig) => {
|
|
3056
|
-
|
|
3139
|
+
var _a;
|
|
3140
|
+
const childInjector = (_a = routerConfig.injector) !== null && _a !== void 0 ? _a : injector;
|
|
3057
3141
|
const childConfig = routerConfig.routes;
|
|
3058
3142
|
const { segmentGroup: splitSegmentGroup, slicedSegments } = split(rawSegmentGroup, consumedSegments, remainingSegments, childConfig);
|
|
3059
3143
|
// See comment on the other call to `split` about why this is necessary.
|
|
3060
3144
|
const segmentGroup = new UrlSegmentGroup(splitSegmentGroup.segments, splitSegmentGroup.children);
|
|
3061
3145
|
if (slicedSegments.length === 0 && segmentGroup.hasChildren()) {
|
|
3062
|
-
const expanded$ = this.expandChildren(
|
|
3146
|
+
const expanded$ = this.expandChildren(childInjector, childConfig, segmentGroup);
|
|
3063
3147
|
return expanded$.pipe(map((children) => new UrlSegmentGroup(consumedSegments, children)));
|
|
3064
3148
|
}
|
|
3065
3149
|
if (childConfig.length === 0 && slicedSegments.length === 0) {
|
|
3066
3150
|
return of(new UrlSegmentGroup(consumedSegments, {}));
|
|
3067
3151
|
}
|
|
3068
3152
|
const matchedOnOutlet = getOutlet(route) === outlet;
|
|
3069
|
-
const expanded$ = this.expandSegment(
|
|
3153
|
+
const expanded$ = this.expandSegment(childInjector, segmentGroup, childConfig, slicedSegments, matchedOnOutlet ? PRIMARY_OUTLET : outlet, true);
|
|
3070
3154
|
return expanded$.pipe(map((cs) => new UrlSegmentGroup(consumedSegments.concat(cs.segments), cs.children)));
|
|
3071
3155
|
}));
|
|
3072
3156
|
}
|
|
3073
|
-
getChildConfig(
|
|
3157
|
+
getChildConfig(injector, route, segments) {
|
|
3074
3158
|
if (route.children) {
|
|
3075
3159
|
// The children belong to the same module
|
|
3076
|
-
return of(
|
|
3160
|
+
return of({ routes: route.children, injector });
|
|
3077
3161
|
}
|
|
3078
3162
|
if (route.loadChildren) {
|
|
3079
3163
|
// lazy children belong to the loaded module
|
|
3080
|
-
if (route.
|
|
3081
|
-
return of(route.
|
|
3164
|
+
if (route._loadedRoutes !== undefined) {
|
|
3165
|
+
return of({ routes: route._loadedRoutes, injector: route._loadedInjector });
|
|
3082
3166
|
}
|
|
3083
|
-
return this.runCanLoadGuards(
|
|
3167
|
+
return this.runCanLoadGuards(injector, route, segments)
|
|
3084
3168
|
.pipe(mergeMap((shouldLoadResult) => {
|
|
3085
3169
|
if (shouldLoadResult) {
|
|
3086
|
-
return this.configLoader.
|
|
3087
|
-
.pipe(
|
|
3088
|
-
route.
|
|
3089
|
-
|
|
3170
|
+
return this.configLoader.loadChildren(injector, route)
|
|
3171
|
+
.pipe(tap((cfg) => {
|
|
3172
|
+
route._loadedRoutes = cfg.routes;
|
|
3173
|
+
route._loadedInjector = cfg.injector;
|
|
3090
3174
|
}));
|
|
3091
3175
|
}
|
|
3092
3176
|
return canLoadFails(route);
|
|
3093
3177
|
}));
|
|
3094
3178
|
}
|
|
3095
|
-
return of(
|
|
3179
|
+
return of({ routes: [], injector });
|
|
3096
3180
|
}
|
|
3097
|
-
runCanLoadGuards(
|
|
3181
|
+
runCanLoadGuards(injector, route, segments) {
|
|
3098
3182
|
const canLoad = route.canLoad;
|
|
3099
3183
|
if (!canLoad || canLoad.length === 0)
|
|
3100
3184
|
return of(true);
|
|
3101
3185
|
const canLoadObservables = canLoad.map((injectionToken) => {
|
|
3102
|
-
const guard =
|
|
3186
|
+
const guard = injector.get(injectionToken);
|
|
3103
3187
|
let guardVal;
|
|
3104
3188
|
if (isCanLoad(guard)) {
|
|
3105
3189
|
guardVal = guard.canLoad(route, segments);
|
|
@@ -3227,8 +3311,8 @@ function squashSegmentGroup(segmentGroup) {
|
|
|
3227
3311
|
* Use of this source code is governed by an MIT-style license that can be
|
|
3228
3312
|
* found in the LICENSE file at https://angular.io/license
|
|
3229
3313
|
*/
|
|
3230
|
-
function applyRedirects(
|
|
3231
|
-
return switchMap(t => applyRedirects$1(
|
|
3314
|
+
function applyRedirects(environmentInjector, configLoader, urlSerializer, config) {
|
|
3315
|
+
return switchMap(t => applyRedirects$1(environmentInjector, configLoader, urlSerializer, t.extractedUrl, config)
|
|
3232
3316
|
.pipe(map(urlAfterRedirects => (Object.assign(Object.assign({}, t), { urlAfterRedirects })))));
|
|
3233
3317
|
}
|
|
3234
3318
|
|
|
@@ -3262,21 +3346,11 @@ function getCanActivateChild(p) {
|
|
|
3262
3346
|
return null;
|
|
3263
3347
|
return { node: p, guards: canActivateChild };
|
|
3264
3348
|
}
|
|
3265
|
-
function getToken(token, snapshot,
|
|
3266
|
-
const
|
|
3267
|
-
const injector =
|
|
3349
|
+
function getToken(token, snapshot, fallbackInjector) {
|
|
3350
|
+
const routeInjector = getClosestRouteInjector(snapshot);
|
|
3351
|
+
const injector = routeInjector !== null && routeInjector !== void 0 ? routeInjector : fallbackInjector;
|
|
3268
3352
|
return injector.get(token);
|
|
3269
3353
|
}
|
|
3270
|
-
function getClosestLoadedConfig(snapshot) {
|
|
3271
|
-
if (!snapshot)
|
|
3272
|
-
return null;
|
|
3273
|
-
for (let s = snapshot.parent; s; s = s.parent) {
|
|
3274
|
-
const route = s.routeConfig;
|
|
3275
|
-
if (route && route._loadedConfig)
|
|
3276
|
-
return route._loadedConfig;
|
|
3277
|
-
}
|
|
3278
|
-
return null;
|
|
3279
|
-
}
|
|
3280
3354
|
function getChildRouteGuards(futureNode, currNode, contexts, futurePath, checks = {
|
|
3281
3355
|
canDeactivateChecks: [],
|
|
3282
3356
|
canActivateChecks: []
|
|
@@ -3520,6 +3594,7 @@ function runCanDeactivate(component, currARS, currRSS, futureRSS, moduleInjector
|
|
|
3520
3594
|
* Use of this source code is governed by an MIT-style license that can be
|
|
3521
3595
|
* found in the LICENSE file at https://angular.io/license
|
|
3522
3596
|
*/
|
|
3597
|
+
const NG_DEV_MODE$2 = typeof ngDevMode === 'undefined' || !!ngDevMode;
|
|
3523
3598
|
class NoMatch {
|
|
3524
3599
|
}
|
|
3525
3600
|
function newObservableError(e) {
|
|
@@ -3628,6 +3703,7 @@ class Recognizer {
|
|
|
3628
3703
|
return null;
|
|
3629
3704
|
}
|
|
3630
3705
|
processSegmentAgainstRoute(route, rawSegment, segments, outlet) {
|
|
3706
|
+
var _a, _b, _c, _d;
|
|
3631
3707
|
if (route.redirectTo || !isImmediateMatch(route, rawSegment, segments, outlet))
|
|
3632
3708
|
return null;
|
|
3633
3709
|
let snapshot;
|
|
@@ -3635,7 +3711,13 @@ class Recognizer {
|
|
|
3635
3711
|
let remainingSegments = [];
|
|
3636
3712
|
if (route.path === '**') {
|
|
3637
3713
|
const params = segments.length > 0 ? last(segments).parameters : {};
|
|
3638
|
-
|
|
3714
|
+
const pathIndexShift = getPathIndexShift(rawSegment) + segments.length;
|
|
3715
|
+
snapshot = new ActivatedRouteSnapshot(segments, params, Object.freeze(Object.assign({}, this.urlTree.queryParams)), this.urlTree.fragment, getData(route), getOutlet(route), (_b = (_a = route.component) !== null && _a !== void 0 ? _a : route._loadedComponent) !== null && _b !== void 0 ? _b : null, route, getSourceSegmentGroup(rawSegment), pathIndexShift, getResolve(route),
|
|
3716
|
+
// NG_DEV_MODE is used to prevent the getCorrectedPathIndexShift function from affecting
|
|
3717
|
+
// production bundle size. This value is intended only to surface a warning to users
|
|
3718
|
+
// depending on `relativeLinkResolution: 'legacy'` in dev mode.
|
|
3719
|
+
(NG_DEV_MODE$2 ? getCorrectedPathIndexShift(rawSegment) + segments.length :
|
|
3720
|
+
pathIndexShift));
|
|
3639
3721
|
}
|
|
3640
3722
|
else {
|
|
3641
3723
|
const result = match(rawSegment, route, segments);
|
|
@@ -3644,7 +3726,9 @@ class Recognizer {
|
|
|
3644
3726
|
}
|
|
3645
3727
|
consumedSegments = result.consumedSegments;
|
|
3646
3728
|
remainingSegments = result.remainingSegments;
|
|
3647
|
-
|
|
3729
|
+
const pathIndexShift = getPathIndexShift(rawSegment) + consumedSegments.length;
|
|
3730
|
+
snapshot = new ActivatedRouteSnapshot(consumedSegments, result.parameters, Object.freeze(Object.assign({}, this.urlTree.queryParams)), this.urlTree.fragment, getData(route), getOutlet(route), (_d = (_c = route.component) !== null && _c !== void 0 ? _c : route._loadedComponent) !== null && _d !== void 0 ? _d : null, route, getSourceSegmentGroup(rawSegment), pathIndexShift, getResolve(route), (NG_DEV_MODE$2 ? getCorrectedPathIndexShift(rawSegment) + consumedSegments.length :
|
|
3731
|
+
pathIndexShift));
|
|
3648
3732
|
}
|
|
3649
3733
|
const childConfig = getChildConfig(route);
|
|
3650
3734
|
const { segmentGroup, slicedSegments } = split(rawSegment, consumedSegments, remainingSegments,
|
|
@@ -3692,7 +3776,7 @@ function getChildConfig(route) {
|
|
|
3692
3776
|
return route.children;
|
|
3693
3777
|
}
|
|
3694
3778
|
if (route.loadChildren) {
|
|
3695
|
-
return route.
|
|
3779
|
+
return route._loadedRoutes;
|
|
3696
3780
|
}
|
|
3697
3781
|
return [];
|
|
3698
3782
|
}
|
|
@@ -3753,11 +3837,22 @@ function getSourceSegmentGroup(segmentGroup) {
|
|
|
3753
3837
|
return s;
|
|
3754
3838
|
}
|
|
3755
3839
|
function getPathIndexShift(segmentGroup) {
|
|
3840
|
+
var _a, _b;
|
|
3841
|
+
let s = segmentGroup;
|
|
3842
|
+
let res = (_a = s._segmentIndexShift) !== null && _a !== void 0 ? _a : 0;
|
|
3843
|
+
while (s._sourceSegment) {
|
|
3844
|
+
s = s._sourceSegment;
|
|
3845
|
+
res += (_b = s._segmentIndexShift) !== null && _b !== void 0 ? _b : 0;
|
|
3846
|
+
}
|
|
3847
|
+
return res - 1;
|
|
3848
|
+
}
|
|
3849
|
+
function getCorrectedPathIndexShift(segmentGroup) {
|
|
3850
|
+
var _a, _b, _c, _d;
|
|
3756
3851
|
let s = segmentGroup;
|
|
3757
|
-
let res = (s.
|
|
3852
|
+
let res = (_b = (_a = s._segmentIndexShiftCorrected) !== null && _a !== void 0 ? _a : s._segmentIndexShift) !== null && _b !== void 0 ? _b : 0;
|
|
3758
3853
|
while (s._sourceSegment) {
|
|
3759
3854
|
s = s._sourceSegment;
|
|
3760
|
-
res += (s.
|
|
3855
|
+
res += (_d = (_c = s._segmentIndexShiftCorrected) !== null && _c !== void 0 ? _c : s._segmentIndexShift) !== null && _d !== void 0 ? _d : 0;
|
|
3761
3856
|
}
|
|
3762
3857
|
return res - 1;
|
|
3763
3858
|
}
|
|
@@ -3827,16 +3922,9 @@ function resolveNode(resolve, futureARS, futureRSS, moduleInjector) {
|
|
|
3827
3922
|
}
|
|
3828
3923
|
const data = {};
|
|
3829
3924
|
return from(keys).pipe(mergeMap(key => getResolver(resolve[key], futureARS, futureRSS, moduleInjector)
|
|
3830
|
-
.pipe(
|
|
3925
|
+
.pipe(first(), tap((value) => {
|
|
3831
3926
|
data[key] = value;
|
|
3832
|
-
}))), takeLast(1),
|
|
3833
|
-
// Ensure all resolvers returned values, otherwise don't emit any "next" and just complete
|
|
3834
|
-
// the chain which will cancel navigation
|
|
3835
|
-
if (getDataKeys(data).length === keys.length) {
|
|
3836
|
-
return of(data);
|
|
3837
|
-
}
|
|
3838
|
-
return EMPTY;
|
|
3839
|
-
}));
|
|
3927
|
+
}))), takeLast(1), mapTo(data), catchError((e) => e instanceof EmptyError ? EMPTY : throwError(e)));
|
|
3840
3928
|
}
|
|
3841
3929
|
function getDataKeys(obj) {
|
|
3842
3930
|
return [...Object.keys(obj), ...Object.getOwnPropertySymbols(obj)];
|
|
@@ -3945,6 +4033,7 @@ class DefaultRouteReuseStrategy extends BaseRouteReuseStrategy {
|
|
|
3945
4033
|
* Use of this source code is governed by an MIT-style license that can be
|
|
3946
4034
|
* found in the LICENSE file at https://angular.io/license
|
|
3947
4035
|
*/
|
|
4036
|
+
const NG_DEV_MODE$1 = typeof ngDevMode === 'undefined' || !!ngDevMode;
|
|
3948
4037
|
/**
|
|
3949
4038
|
* The [DI token](guide/glossary/#di-token) for a router configuration.
|
|
3950
4039
|
*
|
|
@@ -3957,43 +4046,85 @@ class DefaultRouteReuseStrategy extends BaseRouteReuseStrategy {
|
|
|
3957
4046
|
*/
|
|
3958
4047
|
const ROUTES = new InjectionToken('ROUTES');
|
|
3959
4048
|
class RouterConfigLoader {
|
|
3960
|
-
constructor(injector, compiler
|
|
4049
|
+
constructor(injector, compiler) {
|
|
3961
4050
|
this.injector = injector;
|
|
3962
4051
|
this.compiler = compiler;
|
|
3963
|
-
this.
|
|
3964
|
-
this.
|
|
4052
|
+
this.componentLoaders = new WeakMap();
|
|
4053
|
+
this.childrenLoaders = new WeakMap();
|
|
4054
|
+
}
|
|
4055
|
+
loadComponent(route) {
|
|
4056
|
+
if (this.componentLoaders.get(route)) {
|
|
4057
|
+
return this.componentLoaders.get(route);
|
|
4058
|
+
}
|
|
4059
|
+
else if (route._loadedComponent) {
|
|
4060
|
+
return of(route._loadedComponent);
|
|
4061
|
+
}
|
|
4062
|
+
if (this.onLoadStartListener) {
|
|
4063
|
+
this.onLoadStartListener(route);
|
|
4064
|
+
}
|
|
4065
|
+
const loadRunner = wrapIntoObservable(route.loadComponent())
|
|
4066
|
+
.pipe(tap(component => {
|
|
4067
|
+
var _a;
|
|
4068
|
+
if (this.onLoadEndListener) {
|
|
4069
|
+
this.onLoadEndListener(route);
|
|
4070
|
+
}
|
|
4071
|
+
NG_DEV_MODE$1 && assertStandalone((_a = route.path) !== null && _a !== void 0 ? _a : '', component);
|
|
4072
|
+
route._loadedComponent = component;
|
|
4073
|
+
}), finalize(() => {
|
|
4074
|
+
this.componentLoaders.delete(route);
|
|
4075
|
+
}));
|
|
4076
|
+
// Use custom ConnectableObservable as share in runners pipe increasing the bundle size too much
|
|
4077
|
+
const loader = new ConnectableObservable(loadRunner, () => new Subject()).pipe(refCount());
|
|
4078
|
+
this.componentLoaders.set(route, loader);
|
|
4079
|
+
return loader;
|
|
3965
4080
|
}
|
|
3966
|
-
|
|
3967
|
-
if (route
|
|
3968
|
-
return route
|
|
4081
|
+
loadChildren(parentInjector, route) {
|
|
4082
|
+
if (this.childrenLoaders.get(route)) {
|
|
4083
|
+
return this.childrenLoaders.get(route);
|
|
4084
|
+
}
|
|
4085
|
+
else if (route._loadedRoutes) {
|
|
4086
|
+
return of({ routes: route._loadedRoutes, injector: route._loadedInjector });
|
|
3969
4087
|
}
|
|
3970
4088
|
if (this.onLoadStartListener) {
|
|
3971
4089
|
this.onLoadStartListener(route);
|
|
3972
4090
|
}
|
|
3973
|
-
const
|
|
3974
|
-
const loadRunner =
|
|
4091
|
+
const moduleFactoryOrRoutes$ = this.loadModuleFactoryOrRoutes(route.loadChildren);
|
|
4092
|
+
const loadRunner = moduleFactoryOrRoutes$.pipe(map((factoryOrRoutes) => {
|
|
3975
4093
|
if (this.onLoadEndListener) {
|
|
3976
4094
|
this.onLoadEndListener(route);
|
|
3977
4095
|
}
|
|
3978
|
-
|
|
3979
|
-
//
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
|
|
4096
|
+
// This injector comes from the `NgModuleRef` when lazy loading an `NgModule`. There is no
|
|
4097
|
+
// injector associated with lazy loading a `Route` array.
|
|
4098
|
+
let injector;
|
|
4099
|
+
let rawRoutes;
|
|
4100
|
+
let requireStandaloneComponents = false;
|
|
4101
|
+
if (Array.isArray(factoryOrRoutes)) {
|
|
4102
|
+
rawRoutes = factoryOrRoutes;
|
|
4103
|
+
requireStandaloneComponents = true;
|
|
4104
|
+
}
|
|
4105
|
+
else {
|
|
4106
|
+
injector = factoryOrRoutes.create(parentInjector).injector;
|
|
4107
|
+
// When loading a module that doesn't provide `RouterModule.forChild()` preloader
|
|
4108
|
+
// will get stuck in an infinite loop. The child module's Injector will look to
|
|
4109
|
+
// its parent `Injector` when it doesn't find any ROUTES so it will return routes
|
|
4110
|
+
// for it's parent module instead.
|
|
4111
|
+
rawRoutes = flatten(injector.get(ROUTES, [], InjectFlags.Self | InjectFlags.Optional));
|
|
4112
|
+
}
|
|
4113
|
+
const routes = rawRoutes.map(standardizeConfig);
|
|
4114
|
+
NG_DEV_MODE$1 && validateConfig(routes, route.path, requireStandaloneComponents);
|
|
4115
|
+
return { routes, injector };
|
|
4116
|
+
}), finalize(() => {
|
|
4117
|
+
this.childrenLoaders.delete(route);
|
|
3988
4118
|
}));
|
|
3989
4119
|
// Use custom ConnectableObservable as share in runners pipe increasing the bundle size too much
|
|
3990
|
-
|
|
4120
|
+
const loader = new ConnectableObservable(loadRunner, () => new Subject())
|
|
3991
4121
|
.pipe(refCount());
|
|
3992
|
-
|
|
4122
|
+
this.childrenLoaders.set(route, loader);
|
|
4123
|
+
return loader;
|
|
3993
4124
|
}
|
|
3994
|
-
|
|
4125
|
+
loadModuleFactoryOrRoutes(loadChildren) {
|
|
3995
4126
|
return wrapIntoObservable(loadChildren()).pipe(mergeMap((t) => {
|
|
3996
|
-
if (t instanceof NgModuleFactory) {
|
|
4127
|
+
if (t instanceof NgModuleFactory || Array.isArray(t)) {
|
|
3997
4128
|
return of(t);
|
|
3998
4129
|
}
|
|
3999
4130
|
else {
|
|
@@ -4002,6 +4133,11 @@ class RouterConfigLoader {
|
|
|
4002
4133
|
}));
|
|
4003
4134
|
}
|
|
4004
4135
|
}
|
|
4136
|
+
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 });
|
|
4137
|
+
RouterConfigLoader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: RouterConfigLoader });
|
|
4138
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: RouterConfigLoader, decorators: [{
|
|
4139
|
+
type: Injectable
|
|
4140
|
+
}], ctorParameters: function () { return [{ type: i0.Injector }, { type: i0.Compiler }]; } });
|
|
4005
4141
|
|
|
4006
4142
|
/**
|
|
4007
4143
|
* @license
|
|
@@ -4034,6 +4170,7 @@ class DefaultUrlHandlingStrategy {
|
|
|
4034
4170
|
}
|
|
4035
4171
|
}
|
|
4036
4172
|
|
|
4173
|
+
const NG_DEV_MODE = typeof ngDevMode === 'undefined' || !!ngDevMode;
|
|
4037
4174
|
function defaultErrorHandler(error) {
|
|
4038
4175
|
throw error;
|
|
4039
4176
|
}
|
|
@@ -4205,6 +4342,9 @@ class Router {
|
|
|
4205
4342
|
this.canceledNavigationResolution = 'replace';
|
|
4206
4343
|
const onLoadStart = (r) => this.triggerEvent(new RouteConfigLoadStart(r));
|
|
4207
4344
|
const onLoadEnd = (r) => this.triggerEvent(new RouteConfigLoadEnd(r));
|
|
4345
|
+
this.configLoader = injector.get(RouterConfigLoader);
|
|
4346
|
+
this.configLoader.onLoadEndListener = onLoadEnd;
|
|
4347
|
+
this.configLoader.onLoadStartListener = onLoadStart;
|
|
4208
4348
|
this.ngModule = injector.get(NgModuleRef);
|
|
4209
4349
|
this.console = injector.get(ɵConsole);
|
|
4210
4350
|
const ngZone = injector.get(NgZone);
|
|
@@ -4213,7 +4353,6 @@ class Router {
|
|
|
4213
4353
|
this.currentUrlTree = createEmptyUrlTree();
|
|
4214
4354
|
this.rawUrlTree = this.currentUrlTree;
|
|
4215
4355
|
this.browserUrlTree = this.currentUrlTree;
|
|
4216
|
-
this.configLoader = new RouterConfigLoader(injector, compiler, onLoadStart, onLoadEnd);
|
|
4217
4356
|
this.routerState = createEmptyState(this.currentUrlTree, this.rootComponentType);
|
|
4218
4357
|
this.transitions = new BehaviorSubject({
|
|
4219
4358
|
id: 0,
|
|
@@ -4411,6 +4550,26 @@ class Router {
|
|
|
4411
4550
|
skipLocationChange: !!skipLocationChange,
|
|
4412
4551
|
replaceUrl: !!replaceUrl,
|
|
4413
4552
|
});
|
|
4553
|
+
}),
|
|
4554
|
+
// --- LOAD COMPONENTS ---
|
|
4555
|
+
switchTap((t) => {
|
|
4556
|
+
const loadComponents = (route) => {
|
|
4557
|
+
var _a;
|
|
4558
|
+
const loaders = [];
|
|
4559
|
+
if (((_a = route.routeConfig) === null || _a === void 0 ? void 0 : _a.loadComponent) &&
|
|
4560
|
+
!route.routeConfig._loadedComponent) {
|
|
4561
|
+
loaders.push(this.configLoader.loadComponent(route.routeConfig)
|
|
4562
|
+
.pipe(tap(loadedComponent => {
|
|
4563
|
+
route.component = loadedComponent;
|
|
4564
|
+
}), map(() => void 0)));
|
|
4565
|
+
}
|
|
4566
|
+
for (const child of route.children) {
|
|
4567
|
+
loaders.push(...loadComponents(child));
|
|
4568
|
+
}
|
|
4569
|
+
return loaders;
|
|
4570
|
+
};
|
|
4571
|
+
return combineLatest(loadComponents(t.targetSnapshot.root))
|
|
4572
|
+
.pipe(defaultIfEmpty(), take(1));
|
|
4414
4573
|
}), map((t) => {
|
|
4415
4574
|
const targetRouterState = createRouterState(this.routeReuseStrategy, t.targetSnapshot, t.currentRouterState);
|
|
4416
4575
|
return (Object.assign(Object.assign({}, t), { targetRouterState }));
|
|
@@ -4490,23 +4649,17 @@ class Router {
|
|
|
4490
4649
|
t.resolve(false);
|
|
4491
4650
|
}
|
|
4492
4651
|
else {
|
|
4493
|
-
|
|
4494
|
-
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
|
|
4502
|
-
|
|
4503
|
-
|
|
4504
|
-
// the navigation is rejected.
|
|
4505
|
-
replaceUrl: this.urlUpdateStrategy === 'eager' ||
|
|
4506
|
-
isBrowserTriggeredNavigation(t.source)
|
|
4507
|
-
};
|
|
4508
|
-
this.scheduleNavigation(mergedTree, 'imperative', null, extras, { resolve: t.resolve, reject: t.reject, promise: t.promise });
|
|
4509
|
-
}, 0);
|
|
4652
|
+
const mergedTree = this.urlHandlingStrategy.merge(e.url, this.rawUrlTree);
|
|
4653
|
+
const extras = {
|
|
4654
|
+
skipLocationChange: t.extras.skipLocationChange,
|
|
4655
|
+
// The URL is already updated at this point if we have 'eager' URL
|
|
4656
|
+
// updates or if the navigation was triggered by the browser (back
|
|
4657
|
+
// button, URL bar, etc). We want to replace that item in history if
|
|
4658
|
+
// the navigation is rejected.
|
|
4659
|
+
replaceUrl: this.urlUpdateStrategy === 'eager' ||
|
|
4660
|
+
isBrowserTriggeredNavigation(t.source)
|
|
4661
|
+
};
|
|
4662
|
+
this.scheduleNavigation(mergedTree, 'imperative', null, extras, { resolve: t.resolve, reject: t.reject, promise: t.promise });
|
|
4510
4663
|
}
|
|
4511
4664
|
/* All other errors should reset to the router's internal URL reference to
|
|
4512
4665
|
* the pre-error state. */
|
|
@@ -4617,7 +4770,7 @@ class Router {
|
|
|
4617
4770
|
* ```
|
|
4618
4771
|
*/
|
|
4619
4772
|
resetConfig(config) {
|
|
4620
|
-
validateConfig(config);
|
|
4773
|
+
NG_DEV_MODE && validateConfig(config);
|
|
4621
4774
|
this.config = config.map(standardizeConfig);
|
|
4622
4775
|
this.navigated = false;
|
|
4623
4776
|
this.lastSuccessfulId = -1;
|
|
@@ -4975,9 +5128,9 @@ class Router {
|
|
|
4975
5128
|
return { navigationId };
|
|
4976
5129
|
}
|
|
4977
5130
|
}
|
|
4978
|
-
Router.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
4979
|
-
Router.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
4980
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5131
|
+
Router.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: Router, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
|
|
5132
|
+
Router.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: Router });
|
|
5133
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: Router, decorators: [{
|
|
4981
5134
|
type: Injectable
|
|
4982
5135
|
}], ctorParameters: function () { return [{ type: i0.Type }, { type: UrlSerializer }, { type: ChildrenOutletContexts }, { type: i3.Location }, { type: i0.Injector }, { type: i0.Compiler }, { type: undefined }]; } });
|
|
4983
5136
|
function validateCommands(commands) {
|
|
@@ -5169,9 +5322,9 @@ class RouterLink {
|
|
|
5169
5322
|
});
|
|
5170
5323
|
}
|
|
5171
5324
|
}
|
|
5172
|
-
RouterLink.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5173
|
-
RouterLink.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5174
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5325
|
+
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 });
|
|
5326
|
+
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 });
|
|
5327
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: RouterLink, decorators: [{
|
|
5175
5328
|
type: Directive,
|
|
5176
5329
|
args: [{ selector: ':not(a):not(area)[routerLink]' }]
|
|
5177
5330
|
}], ctorParameters: function () {
|
|
@@ -5290,9 +5443,9 @@ class RouterLinkWithHref {
|
|
|
5290
5443
|
});
|
|
5291
5444
|
}
|
|
5292
5445
|
}
|
|
5293
|
-
RouterLinkWithHref.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5294
|
-
RouterLinkWithHref.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5295
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5446
|
+
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 });
|
|
5447
|
+
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 });
|
|
5448
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: RouterLinkWithHref, decorators: [{
|
|
5296
5449
|
type: Directive,
|
|
5297
5450
|
args: [{ selector: 'a[routerLink],area[routerLink]' }]
|
|
5298
5451
|
}], ctorParameters: function () { return [{ type: Router }, { type: ActivatedRoute }, { type: i3.LocationStrategy }]; }, propDecorators: { target: [{
|
|
@@ -5389,6 +5542,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.12",
|
|
|
5389
5542
|
* </div>
|
|
5390
5543
|
* ```
|
|
5391
5544
|
*
|
|
5545
|
+
* The `RouterLinkActive` directive can also be used to set the aria-current attribute
|
|
5546
|
+
* to provide an alternative distinction for active elements to visually impaired users.
|
|
5547
|
+
*
|
|
5548
|
+
* For example, the following code adds the 'active' class to the Home Page link when it is
|
|
5549
|
+
* indeed active and in such case also sets its aria-current attribute to 'page':
|
|
5550
|
+
*
|
|
5551
|
+
* ```
|
|
5552
|
+
* <a routerLink="/" routerLinkActive="active" ariaCurrentWhenActive="page">Home Page</a>
|
|
5553
|
+
* ```
|
|
5554
|
+
*
|
|
5392
5555
|
* @ngModule RouterModule
|
|
5393
5556
|
*
|
|
5394
5557
|
* @publicApi
|
|
@@ -5484,6 +5647,12 @@ class RouterLinkActive {
|
|
|
5484
5647
|
this.renderer.removeClass(this.element.nativeElement, c);
|
|
5485
5648
|
}
|
|
5486
5649
|
});
|
|
5650
|
+
if (hasActiveLinks && this.ariaCurrentWhenActive !== undefined) {
|
|
5651
|
+
this.renderer.setAttribute(this.element.nativeElement, 'aria-current', this.ariaCurrentWhenActive.toString());
|
|
5652
|
+
}
|
|
5653
|
+
else {
|
|
5654
|
+
this.renderer.removeAttribute(this.element.nativeElement, 'aria-current');
|
|
5655
|
+
}
|
|
5487
5656
|
// Emit on isActiveChange after classes are updated
|
|
5488
5657
|
this.isActiveChange.emit(hasActiveLinks);
|
|
5489
5658
|
}
|
|
@@ -5503,9 +5672,9 @@ class RouterLinkActive {
|
|
|
5503
5672
|
this.links.some(isActiveCheckFn) || this.linksWithHrefs.some(isActiveCheckFn);
|
|
5504
5673
|
}
|
|
5505
5674
|
}
|
|
5506
|
-
RouterLinkActive.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5507
|
-
RouterLinkActive.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5508
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5675
|
+
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 });
|
|
5676
|
+
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 });
|
|
5677
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: RouterLinkActive, decorators: [{
|
|
5509
5678
|
type: Directive,
|
|
5510
5679
|
args: [{
|
|
5511
5680
|
selector: '[routerLinkActive]',
|
|
@@ -5525,6 +5694,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.12",
|
|
|
5525
5694
|
args: [RouterLinkWithHref, { descendants: true }]
|
|
5526
5695
|
}], routerLinkActiveOptions: [{
|
|
5527
5696
|
type: Input
|
|
5697
|
+
}], ariaCurrentWhenActive: [{
|
|
5698
|
+
type: Input
|
|
5528
5699
|
}], isActiveChange: [{
|
|
5529
5700
|
type: Output
|
|
5530
5701
|
}], routerLinkActive: [{
|
|
@@ -5609,9 +5780,9 @@ class DefaultTitleStrategy extends TitleStrategy {
|
|
|
5609
5780
|
}
|
|
5610
5781
|
}
|
|
5611
5782
|
}
|
|
5612
|
-
DefaultTitleStrategy.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5613
|
-
DefaultTitleStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5614
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5783
|
+
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 });
|
|
5784
|
+
DefaultTitleStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: DefaultTitleStrategy, providedIn: 'root' });
|
|
5785
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: DefaultTitleStrategy, decorators: [{
|
|
5615
5786
|
type: Injectable,
|
|
5616
5787
|
args: [{ providedIn: 'root' }]
|
|
5617
5788
|
}], ctorParameters: function () { return [{ type: i1.Title }]; } });
|
|
@@ -5675,13 +5846,11 @@ class NoPreloading {
|
|
|
5675
5846
|
* @publicApi
|
|
5676
5847
|
*/
|
|
5677
5848
|
class RouterPreloader {
|
|
5678
|
-
constructor(router, compiler, injector, preloadingStrategy) {
|
|
5849
|
+
constructor(router, compiler, injector, preloadingStrategy, loader) {
|
|
5679
5850
|
this.router = router;
|
|
5680
5851
|
this.injector = injector;
|
|
5681
5852
|
this.preloadingStrategy = preloadingStrategy;
|
|
5682
|
-
|
|
5683
|
-
const onEndLoad = (r) => router.triggerEvent(new RouteConfigLoadEnd(r));
|
|
5684
|
-
this.loader = new RouterConfigLoader(injector, compiler, onStartLoad, onEndLoad);
|
|
5853
|
+
this.loader = loader;
|
|
5685
5854
|
}
|
|
5686
5855
|
setUpPreloading() {
|
|
5687
5856
|
this.subscription =
|
|
@@ -5690,8 +5859,7 @@ class RouterPreloader {
|
|
|
5690
5859
|
.subscribe(() => { });
|
|
5691
5860
|
}
|
|
5692
5861
|
preload() {
|
|
5693
|
-
|
|
5694
|
-
return this.processRoutes(ngModule, this.router.config);
|
|
5862
|
+
return this.processRoutes(this.injector, this.router.config);
|
|
5695
5863
|
}
|
|
5696
5864
|
/** @nodoc */
|
|
5697
5865
|
ngOnDestroy() {
|
|
@@ -5699,41 +5867,61 @@ class RouterPreloader {
|
|
|
5699
5867
|
this.subscription.unsubscribe();
|
|
5700
5868
|
}
|
|
5701
5869
|
}
|
|
5702
|
-
processRoutes(
|
|
5870
|
+
processRoutes(injector, routes) {
|
|
5871
|
+
var _a, _b, _c;
|
|
5703
5872
|
const res = [];
|
|
5704
5873
|
for (const route of routes) {
|
|
5705
|
-
|
|
5706
|
-
|
|
5707
|
-
|
|
5708
|
-
res.push(this.processRoutes(childConfig.module, childConfig.routes));
|
|
5709
|
-
// no config loaded, fetch the config
|
|
5874
|
+
if (route.providers && !route._injector) {
|
|
5875
|
+
route._injector =
|
|
5876
|
+
createEnvironmentInjector(route.providers, injector, `Route: ${route.path}`);
|
|
5710
5877
|
}
|
|
5711
|
-
|
|
5712
|
-
|
|
5713
|
-
|
|
5878
|
+
const injectorForCurrentRoute = (_a = route._injector) !== null && _a !== void 0 ? _a : injector;
|
|
5879
|
+
const injectorForChildren = (_b = route._loadedInjector) !== null && _b !== void 0 ? _b : injectorForCurrentRoute;
|
|
5880
|
+
if ((route.loadChildren && !route._loadedRoutes) ||
|
|
5881
|
+
(route.loadComponent && !route._loadedComponent)) {
|
|
5882
|
+
res.push(this.preloadConfig(injectorForCurrentRoute, route));
|
|
5714
5883
|
}
|
|
5715
|
-
else if (route.children) {
|
|
5716
|
-
res.push(this.processRoutes(
|
|
5884
|
+
else if (route.children || route._loadedRoutes) {
|
|
5885
|
+
res.push(this.processRoutes(injectorForChildren, ((_c = route.children) !== null && _c !== void 0 ? _c : route._loadedRoutes)));
|
|
5717
5886
|
}
|
|
5718
5887
|
}
|
|
5719
|
-
return from(res).pipe(mergeAll()
|
|
5888
|
+
return from(res).pipe(mergeAll());
|
|
5720
5889
|
}
|
|
5721
|
-
preloadConfig(
|
|
5890
|
+
preloadConfig(injector, route) {
|
|
5722
5891
|
return this.preloadingStrategy.preload(route, () => {
|
|
5723
|
-
|
|
5724
|
-
|
|
5725
|
-
|
|
5726
|
-
|
|
5727
|
-
|
|
5892
|
+
let loadedChildren$;
|
|
5893
|
+
if (route.loadChildren && route.canLoad === undefined) {
|
|
5894
|
+
loadedChildren$ = this.loader.loadChildren(injector, route);
|
|
5895
|
+
}
|
|
5896
|
+
else {
|
|
5897
|
+
loadedChildren$ = of(null);
|
|
5898
|
+
}
|
|
5899
|
+
const recursiveLoadChildren$ = loadedChildren$.pipe(mergeMap((config) => {
|
|
5900
|
+
var _a;
|
|
5901
|
+
if (config === null) {
|
|
5902
|
+
return of(void 0);
|
|
5903
|
+
}
|
|
5904
|
+
route._loadedRoutes = config.routes;
|
|
5905
|
+
route._loadedInjector = config.injector;
|
|
5906
|
+
// If the loaded config was a module, use that as the module/module injector going
|
|
5907
|
+
// forward. Otherwise, continue using the current module/module injector.
|
|
5908
|
+
return this.processRoutes((_a = config.injector) !== null && _a !== void 0 ? _a : injector, config.routes);
|
|
5728
5909
|
}));
|
|
5910
|
+
if (route.loadComponent && !route._loadedComponent) {
|
|
5911
|
+
const loadComponent$ = this.loader.loadComponent(route);
|
|
5912
|
+
return from([recursiveLoadChildren$, loadComponent$]).pipe(mergeAll());
|
|
5913
|
+
}
|
|
5914
|
+
else {
|
|
5915
|
+
return recursiveLoadChildren$;
|
|
5916
|
+
}
|
|
5729
5917
|
});
|
|
5730
5918
|
}
|
|
5731
5919
|
}
|
|
5732
|
-
RouterPreloader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5733
|
-
RouterPreloader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5734
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5920
|
+
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 });
|
|
5921
|
+
RouterPreloader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: RouterPreloader });
|
|
5922
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: RouterPreloader, decorators: [{
|
|
5735
5923
|
type: Injectable
|
|
5736
|
-
}], ctorParameters: function () { return [{ type: Router }, { type: i0.Compiler }, { type: i0.
|
|
5924
|
+
}], ctorParameters: function () { return [{ type: Router }, { type: i0.Compiler }, { type: i0.EnvironmentInjector }, { type: PreloadingStrategy }, { type: RouterConfigLoader }]; } });
|
|
5737
5925
|
|
|
5738
5926
|
class RouterScroller {
|
|
5739
5927
|
constructor(router,
|
|
@@ -5810,9 +5998,9 @@ class RouterScroller {
|
|
|
5810
5998
|
}
|
|
5811
5999
|
}
|
|
5812
6000
|
}
|
|
5813
|
-
RouterScroller.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5814
|
-
RouterScroller.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5815
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
6001
|
+
RouterScroller.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: RouterScroller, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
|
|
6002
|
+
RouterScroller.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: RouterScroller });
|
|
6003
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: RouterScroller, decorators: [{
|
|
5816
6004
|
type: Injectable
|
|
5817
6005
|
}], ctorParameters: function () { return [{ type: Router }, { type: i3.ViewportScroller }, { type: undefined }]; } });
|
|
5818
6006
|
|
|
@@ -5855,6 +6043,7 @@ const ROUTER_PROVIDERS = [
|
|
|
5855
6043
|
NoPreloading,
|
|
5856
6044
|
PreloadAllModules,
|
|
5857
6045
|
{ provide: ROUTER_CONFIGURATION, useValue: { enableTracing: false } },
|
|
6046
|
+
RouterConfigLoader,
|
|
5858
6047
|
];
|
|
5859
6048
|
function routerNgProbeToken() {
|
|
5860
6049
|
return new NgProbeToken('Router', Router);
|
|
@@ -5953,10 +6142,10 @@ class RouterModule {
|
|
|
5953
6142
|
return { ngModule: RouterModule, providers: [provideRoutes(routes)] };
|
|
5954
6143
|
}
|
|
5955
6144
|
}
|
|
5956
|
-
RouterModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5957
|
-
RouterModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5958
|
-
RouterModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
5959
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
6145
|
+
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 });
|
|
6146
|
+
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] });
|
|
6147
|
+
RouterModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: RouterModule });
|
|
6148
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: RouterModule, decorators: [{
|
|
5960
6149
|
type: NgModule,
|
|
5961
6150
|
args: [{
|
|
5962
6151
|
declarations: ROUTER_DIRECTIVES,
|
|
@@ -6138,9 +6327,9 @@ class RouterInitializer {
|
|
|
6138
6327
|
this.destroyed = true;
|
|
6139
6328
|
}
|
|
6140
6329
|
}
|
|
6141
|
-
RouterInitializer.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
6142
|
-
RouterInitializer.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
6143
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
6330
|
+
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 });
|
|
6331
|
+
RouterInitializer.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: RouterInitializer });
|
|
6332
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.15", ngImport: i0, type: RouterInitializer, decorators: [{
|
|
6144
6333
|
type: Injectable
|
|
6145
6334
|
}], ctorParameters: function () { return [{ type: i0.Injector }]; } });
|
|
6146
6335
|
function getAppInitializer(r) {
|
|
@@ -6180,7 +6369,7 @@ function provideRouterInitializer() {
|
|
|
6180
6369
|
/**
|
|
6181
6370
|
* @publicApi
|
|
6182
6371
|
*/
|
|
6183
|
-
const VERSION = new Version('14.0.0-next.
|
|
6372
|
+
const VERSION = new Version('14.0.0-next.15');
|
|
6184
6373
|
|
|
6185
6374
|
/**
|
|
6186
6375
|
* @license
|