@angular/router 14.0.0-next.9 → 14.0.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2020/src/apply_redirects.mjs +52 -48
- 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/events.mjs +57 -1
- package/esm2020/src/index.mjs +1 -1
- 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 +14 -24
- package/esm2020/src/page_title_strategy.mjs +3 -3
- package/esm2020/src/recognize.mjs +24 -6
- package/esm2020/src/router.mjs +43 -25
- package/esm2020/src/router_config_loader.mjs +74 -27
- package/esm2020/src/router_module.mjs +14 -14
- 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 +4 -4
- package/esm2020/src/url_tree.mjs +1 -1
- package/esm2020/src/utils/config.mjs +86 -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 +927 -670
- package/fesm2015/router.mjs.map +1 -1
- package/fesm2015/testing.mjs +5 -5
- package/fesm2015/upgrade.mjs +1 -1
- package/fesm2020/router.mjs +912 -673
- 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} +3858 -3730
- package/package.json +9 -9
- 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-
|
|
2
|
+
* @license Angular v14.0.0-rc.2
|
|
3
3
|
* (c) 2010-2022 Google LLC. https://angular.io/
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import * as i0 from '@angular/core';
|
|
8
|
-
import { ɵisObservable, ɵisPromise, EventEmitter, Directive, Attribute, Output, Component,
|
|
8
|
+
import { ɵisObservable, ɵisPromise, EventEmitter, Directive, Attribute, Output, Component, createEnvironmentInjector, ɵisStandalone, ComponentFactoryResolver, 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';
|
|
@@ -69,6 +69,7 @@ class NavigationStart extends RouterEvent {
|
|
|
69
69
|
/** @docsNotRequired */
|
|
70
70
|
restoredState = null) {
|
|
71
71
|
super(id, url);
|
|
72
|
+
this.type = 0 /* EventType.NavigationStart */;
|
|
72
73
|
this.navigationTrigger = navigationTrigger;
|
|
73
74
|
this.restoredState = restoredState;
|
|
74
75
|
}
|
|
@@ -96,6 +97,7 @@ class NavigationEnd extends RouterEvent {
|
|
|
96
97
|
urlAfterRedirects) {
|
|
97
98
|
super(id, url);
|
|
98
99
|
this.urlAfterRedirects = urlAfterRedirects;
|
|
100
|
+
this.type = 1 /* EventType.NavigationEnd */;
|
|
99
101
|
}
|
|
100
102
|
/** @docsNotRequired */
|
|
101
103
|
toString() {
|
|
@@ -123,6 +125,7 @@ class NavigationCancel extends RouterEvent {
|
|
|
123
125
|
reason) {
|
|
124
126
|
super(id, url);
|
|
125
127
|
this.reason = reason;
|
|
128
|
+
this.type = 2 /* EventType.NavigationCancel */;
|
|
126
129
|
}
|
|
127
130
|
/** @docsNotRequired */
|
|
128
131
|
toString() {
|
|
@@ -148,6 +151,7 @@ class NavigationError extends RouterEvent {
|
|
|
148
151
|
error) {
|
|
149
152
|
super(id, url);
|
|
150
153
|
this.error = error;
|
|
154
|
+
this.type = 3 /* EventType.NavigationError */;
|
|
151
155
|
}
|
|
152
156
|
/** @docsNotRequired */
|
|
153
157
|
toString() {
|
|
@@ -172,6 +176,7 @@ class RoutesRecognized extends RouterEvent {
|
|
|
172
176
|
super(id, url);
|
|
173
177
|
this.urlAfterRedirects = urlAfterRedirects;
|
|
174
178
|
this.state = state;
|
|
179
|
+
this.type = 4 /* EventType.RoutesRecognized */;
|
|
175
180
|
}
|
|
176
181
|
/** @docsNotRequired */
|
|
177
182
|
toString() {
|
|
@@ -198,6 +203,7 @@ class GuardsCheckStart extends RouterEvent {
|
|
|
198
203
|
super(id, url);
|
|
199
204
|
this.urlAfterRedirects = urlAfterRedirects;
|
|
200
205
|
this.state = state;
|
|
206
|
+
this.type = 7 /* EventType.GuardsCheckStart */;
|
|
201
207
|
}
|
|
202
208
|
toString() {
|
|
203
209
|
return `GuardsCheckStart(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`;
|
|
@@ -226,6 +232,7 @@ class GuardsCheckEnd extends RouterEvent {
|
|
|
226
232
|
this.urlAfterRedirects = urlAfterRedirects;
|
|
227
233
|
this.state = state;
|
|
228
234
|
this.shouldActivate = shouldActivate;
|
|
235
|
+
this.type = 8 /* EventType.GuardsCheckEnd */;
|
|
229
236
|
}
|
|
230
237
|
toString() {
|
|
231
238
|
return `GuardsCheckEnd(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state}, shouldActivate: ${this.shouldActivate})`;
|
|
@@ -254,6 +261,7 @@ class ResolveStart extends RouterEvent {
|
|
|
254
261
|
super(id, url);
|
|
255
262
|
this.urlAfterRedirects = urlAfterRedirects;
|
|
256
263
|
this.state = state;
|
|
264
|
+
this.type = 5 /* EventType.ResolveStart */;
|
|
257
265
|
}
|
|
258
266
|
toString() {
|
|
259
267
|
return `ResolveStart(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`;
|
|
@@ -278,6 +286,7 @@ class ResolveEnd extends RouterEvent {
|
|
|
278
286
|
super(id, url);
|
|
279
287
|
this.urlAfterRedirects = urlAfterRedirects;
|
|
280
288
|
this.state = state;
|
|
289
|
+
this.type = 6 /* EventType.ResolveEnd */;
|
|
281
290
|
}
|
|
282
291
|
toString() {
|
|
283
292
|
return `ResolveEnd(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`;
|
|
@@ -295,6 +304,7 @@ class RouteConfigLoadStart {
|
|
|
295
304
|
/** @docsNotRequired */
|
|
296
305
|
route) {
|
|
297
306
|
this.route = route;
|
|
307
|
+
this.type = 9 /* EventType.RouteConfigLoadStart */;
|
|
298
308
|
}
|
|
299
309
|
toString() {
|
|
300
310
|
return `RouteConfigLoadStart(path: ${this.route.path})`;
|
|
@@ -312,6 +322,7 @@ class RouteConfigLoadEnd {
|
|
|
312
322
|
/** @docsNotRequired */
|
|
313
323
|
route) {
|
|
314
324
|
this.route = route;
|
|
325
|
+
this.type = 10 /* EventType.RouteConfigLoadEnd */;
|
|
315
326
|
}
|
|
316
327
|
toString() {
|
|
317
328
|
return `RouteConfigLoadEnd(path: ${this.route.path})`;
|
|
@@ -330,6 +341,7 @@ class ChildActivationStart {
|
|
|
330
341
|
/** @docsNotRequired */
|
|
331
342
|
snapshot) {
|
|
332
343
|
this.snapshot = snapshot;
|
|
344
|
+
this.type = 11 /* EventType.ChildActivationStart */;
|
|
333
345
|
}
|
|
334
346
|
toString() {
|
|
335
347
|
const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || '';
|
|
@@ -348,6 +360,7 @@ class ChildActivationEnd {
|
|
|
348
360
|
/** @docsNotRequired */
|
|
349
361
|
snapshot) {
|
|
350
362
|
this.snapshot = snapshot;
|
|
363
|
+
this.type = 12 /* EventType.ChildActivationEnd */;
|
|
351
364
|
}
|
|
352
365
|
toString() {
|
|
353
366
|
const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || '';
|
|
@@ -367,6 +380,7 @@ class ActivationStart {
|
|
|
367
380
|
/** @docsNotRequired */
|
|
368
381
|
snapshot) {
|
|
369
382
|
this.snapshot = snapshot;
|
|
383
|
+
this.type = 13 /* EventType.ActivationStart */;
|
|
370
384
|
}
|
|
371
385
|
toString() {
|
|
372
386
|
const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || '';
|
|
@@ -386,6 +400,7 @@ class ActivationEnd {
|
|
|
386
400
|
/** @docsNotRequired */
|
|
387
401
|
snapshot) {
|
|
388
402
|
this.snapshot = snapshot;
|
|
403
|
+
this.type = 14 /* EventType.ActivationEnd */;
|
|
389
404
|
}
|
|
390
405
|
toString() {
|
|
391
406
|
const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || '';
|
|
@@ -408,12 +423,54 @@ class Scroll {
|
|
|
408
423
|
this.routerEvent = routerEvent;
|
|
409
424
|
this.position = position;
|
|
410
425
|
this.anchor = anchor;
|
|
426
|
+
this.type = 15 /* EventType.Scroll */;
|
|
411
427
|
}
|
|
412
428
|
toString() {
|
|
413
429
|
const pos = this.position ? `${this.position[0]}, ${this.position[1]}` : null;
|
|
414
430
|
return `Scroll(anchor: '${this.anchor}', position: '${pos}')`;
|
|
415
431
|
}
|
|
416
432
|
}
|
|
433
|
+
function stringifyEvent(routerEvent) {
|
|
434
|
+
var _a, _b, _c, _d;
|
|
435
|
+
if (!('type' in routerEvent)) {
|
|
436
|
+
return `Unknown Router Event: ${routerEvent.constructor.name}`;
|
|
437
|
+
}
|
|
438
|
+
switch (routerEvent.type) {
|
|
439
|
+
case 14 /* EventType.ActivationEnd */:
|
|
440
|
+
return `ActivationEnd(path: '${((_a = routerEvent.snapshot.routeConfig) === null || _a === void 0 ? void 0 : _a.path) || ''}')`;
|
|
441
|
+
case 13 /* EventType.ActivationStart */:
|
|
442
|
+
return `ActivationStart(path: '${((_b = routerEvent.snapshot.routeConfig) === null || _b === void 0 ? void 0 : _b.path) || ''}')`;
|
|
443
|
+
case 12 /* EventType.ChildActivationEnd */:
|
|
444
|
+
return `ChildActivationEnd(path: '${((_c = routerEvent.snapshot.routeConfig) === null || _c === void 0 ? void 0 : _c.path) || ''}')`;
|
|
445
|
+
case 11 /* EventType.ChildActivationStart */:
|
|
446
|
+
return `ChildActivationStart(path: '${((_d = routerEvent.snapshot.routeConfig) === null || _d === void 0 ? void 0 : _d.path) || ''}')`;
|
|
447
|
+
case 8 /* EventType.GuardsCheckEnd */:
|
|
448
|
+
return `GuardsCheckEnd(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state}, shouldActivate: ${routerEvent.shouldActivate})`;
|
|
449
|
+
case 7 /* EventType.GuardsCheckStart */:
|
|
450
|
+
return `GuardsCheckStart(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`;
|
|
451
|
+
case 2 /* EventType.NavigationCancel */:
|
|
452
|
+
return `NavigationCancel(id: ${routerEvent.id}, url: '${routerEvent.url}')`;
|
|
453
|
+
case 1 /* EventType.NavigationEnd */:
|
|
454
|
+
return `NavigationEnd(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}')`;
|
|
455
|
+
case 3 /* EventType.NavigationError */:
|
|
456
|
+
return `NavigationError(id: ${routerEvent.id}, url: '${routerEvent.url}', error: ${routerEvent.error})`;
|
|
457
|
+
case 0 /* EventType.NavigationStart */:
|
|
458
|
+
return `NavigationStart(id: ${routerEvent.id}, url: '${routerEvent.url}')`;
|
|
459
|
+
case 6 /* EventType.ResolveEnd */:
|
|
460
|
+
return `ResolveEnd(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`;
|
|
461
|
+
case 5 /* EventType.ResolveStart */:
|
|
462
|
+
return `ResolveStart(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`;
|
|
463
|
+
case 10 /* EventType.RouteConfigLoadEnd */:
|
|
464
|
+
return `RouteConfigLoadEnd(path: ${routerEvent.route.path})`;
|
|
465
|
+
case 9 /* EventType.RouteConfigLoadStart */:
|
|
466
|
+
return `RouteConfigLoadStart(path: ${routerEvent.route.path})`;
|
|
467
|
+
case 4 /* EventType.RoutesRecognized */:
|
|
468
|
+
return `RoutesRecognized(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`;
|
|
469
|
+
case 15 /* EventType.Scroll */:
|
|
470
|
+
const pos = routerEvent.position ? `${routerEvent.position[0]}, ${routerEvent.position[1]}` : null;
|
|
471
|
+
return `Scroll(anchor: '${routerEvent.anchor}', position: '${pos}')`;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
417
474
|
|
|
418
475
|
/**
|
|
419
476
|
* @license
|
|
@@ -1362,7 +1419,6 @@ class ActivatedRoute {
|
|
|
1362
1419
|
/** The outlet name of the route, a constant. */
|
|
1363
1420
|
outlet,
|
|
1364
1421
|
/** The component of the route, a constant. */
|
|
1365
|
-
// TODO(vsavkin): remove |string
|
|
1366
1422
|
component, futureSnapshot) {
|
|
1367
1423
|
this.url = url;
|
|
1368
1424
|
this.params = params;
|
|
@@ -1454,9 +1510,10 @@ function inheritedParamsDataResolve(route, paramsInheritanceStrategy = 'emptyOnl
|
|
|
1454
1510
|
/** @internal */
|
|
1455
1511
|
function flattenInherited(pathFromRoot) {
|
|
1456
1512
|
return pathFromRoot.reduce((res, curr) => {
|
|
1513
|
+
var _a;
|
|
1457
1514
|
const params = Object.assign(Object.assign({}, res.params), curr.params);
|
|
1458
1515
|
const data = Object.assign(Object.assign({}, res.data), curr.data);
|
|
1459
|
-
const resolve = Object.assign(Object.assign({}, res.resolve), curr._resolvedData);
|
|
1516
|
+
const resolve = Object.assign(Object.assign(Object.assign(Object.assign({}, curr.data), res.resolve), (_a = curr.routeConfig) === null || _a === void 0 ? void 0 : _a.data), curr._resolvedData);
|
|
1460
1517
|
return { params, data, resolve };
|
|
1461
1518
|
}, { params: {}, data: {}, resolve: {} });
|
|
1462
1519
|
}
|
|
@@ -1517,7 +1574,7 @@ class ActivatedRouteSnapshot {
|
|
|
1517
1574
|
/** The outlet name of the route */
|
|
1518
1575
|
outlet,
|
|
1519
1576
|
/** The component of the route */
|
|
1520
|
-
component, routeConfig, urlSegment, lastPathIndex, resolve) {
|
|
1577
|
+
component, routeConfig, urlSegment, lastPathIndex, resolve, correctedLastPathIndex) {
|
|
1521
1578
|
this.url = url;
|
|
1522
1579
|
this.params = params;
|
|
1523
1580
|
this.queryParams = queryParams;
|
|
@@ -1528,6 +1585,7 @@ class ActivatedRouteSnapshot {
|
|
|
1528
1585
|
this.routeConfig = routeConfig;
|
|
1529
1586
|
this._urlSegment = urlSegment;
|
|
1530
1587
|
this._lastPathIndex = lastPathIndex;
|
|
1588
|
+
this._correctedLastPathIndex = correctedLastPathIndex !== null && correctedLastPathIndex !== void 0 ? correctedLastPathIndex : lastPathIndex;
|
|
1531
1589
|
this._resolve = resolve;
|
|
1532
1590
|
}
|
|
1533
1591
|
/** The root of the router state */
|
|
@@ -1712,6 +1770,7 @@ function createActivatedRoute(c) {
|
|
|
1712
1770
|
* found in the LICENSE file at https://angular.io/license
|
|
1713
1771
|
*/
|
|
1714
1772
|
function createUrlTree(route, urlTree, commands, queryParams, fragment) {
|
|
1773
|
+
var _a, _b;
|
|
1715
1774
|
if (commands.length === 0) {
|
|
1716
1775
|
return tree(urlTree.root, urlTree.root, urlTree.root, queryParams, fragment);
|
|
1717
1776
|
}
|
|
@@ -1719,11 +1778,27 @@ function createUrlTree(route, urlTree, commands, queryParams, fragment) {
|
|
|
1719
1778
|
if (nav.toRoot()) {
|
|
1720
1779
|
return tree(urlTree.root, urlTree.root, new UrlSegmentGroup([], {}), queryParams, fragment);
|
|
1721
1780
|
}
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1781
|
+
function createTreeUsingPathIndex(lastPathIndex) {
|
|
1782
|
+
var _a;
|
|
1783
|
+
const startingPosition = findStartingPosition(nav, urlTree, (_a = route.snapshot) === null || _a === void 0 ? void 0 : _a._urlSegment, lastPathIndex);
|
|
1784
|
+
const segmentGroup = startingPosition.processChildren ?
|
|
1785
|
+
updateSegmentGroupChildren(startingPosition.segmentGroup, startingPosition.index, nav.commands) :
|
|
1786
|
+
updateSegmentGroup(startingPosition.segmentGroup, startingPosition.index, nav.commands);
|
|
1787
|
+
return tree(urlTree.root, startingPosition.segmentGroup, segmentGroup, queryParams, fragment);
|
|
1788
|
+
}
|
|
1789
|
+
// Note: The types should disallow `snapshot` from being `undefined` but due to test mocks, this
|
|
1790
|
+
// may be the case. Since we try to access it at an earlier point before the refactor to add the
|
|
1791
|
+
// warning for `relativeLinkResolution: 'legacy'`, this may cause failures in tests where it
|
|
1792
|
+
// didn't before.
|
|
1793
|
+
const result = createTreeUsingPathIndex((_a = route.snapshot) === null || _a === void 0 ? void 0 : _a._lastPathIndex);
|
|
1794
|
+
// Check if application is relying on `relativeLinkResolution: 'legacy'`
|
|
1795
|
+
if (typeof ngDevMode === 'undefined' || !!ngDevMode) {
|
|
1796
|
+
const correctedResult = createTreeUsingPathIndex((_b = route.snapshot) === null || _b === void 0 ? void 0 : _b._correctedLastPathIndex);
|
|
1797
|
+
if (correctedResult.toString() !== result.toString()) {
|
|
1798
|
+
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.`);
|
|
1799
|
+
}
|
|
1800
|
+
}
|
|
1801
|
+
return result;
|
|
1727
1802
|
}
|
|
1728
1803
|
function isMatrixParams(command) {
|
|
1729
1804
|
return typeof command === 'object' && command != null && !command.outlets && !command.segmentPath;
|
|
@@ -1828,12 +1903,11 @@ class Position {
|
|
|
1828
1903
|
this.index = index;
|
|
1829
1904
|
}
|
|
1830
1905
|
}
|
|
1831
|
-
function findStartingPosition(nav, tree,
|
|
1906
|
+
function findStartingPosition(nav, tree, segmentGroup, lastPathIndex) {
|
|
1832
1907
|
if (nav.isAbsolute) {
|
|
1833
1908
|
return new Position(tree.root, true, 0);
|
|
1834
1909
|
}
|
|
1835
|
-
if (
|
|
1836
|
-
const segmentGroup = route.snapshot._urlSegment;
|
|
1910
|
+
if (lastPathIndex === -1) {
|
|
1837
1911
|
// Pathless ActivatedRoute has _lastPathIndex === -1 but should not process children
|
|
1838
1912
|
// see issue #26224, #13011, #35687
|
|
1839
1913
|
// However, if the ActivatedRoute is the root we should process children like above.
|
|
@@ -1841,8 +1915,8 @@ function findStartingPosition(nav, tree, route) {
|
|
|
1841
1915
|
return new Position(segmentGroup, processChildren, 0);
|
|
1842
1916
|
}
|
|
1843
1917
|
const modifier = isMatrixParams(nav.commands[0]) ? 0 : 1;
|
|
1844
|
-
const index =
|
|
1845
|
-
return createPositionApplyingDoubleDots(
|
|
1918
|
+
const index = lastPathIndex + modifier;
|
|
1919
|
+
return createPositionApplyingDoubleDots(segmentGroup, index, nav.numberOfDoubleDots);
|
|
1846
1920
|
}
|
|
1847
1921
|
function createPositionApplyingDoubleDots(group, index, numberOfDoubleDots) {
|
|
1848
1922
|
let g = group;
|
|
@@ -2005,181 +2079,76 @@ function compare(path, params, segment) {
|
|
|
2005
2079
|
* Use of this source code is governed by an MIT-style license that can be
|
|
2006
2080
|
* found in the LICENSE file at https://angular.io/license
|
|
2007
2081
|
*/
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
class
|
|
2014
|
-
constructor(
|
|
2015
|
-
this.
|
|
2016
|
-
this.
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
this.
|
|
2024
|
-
|
|
2025
|
-
this.activateChildRoutes(futureRoot, currRoot, parentContexts);
|
|
2026
|
-
}
|
|
2027
|
-
// De-activate the child route that are not re-used for the future state
|
|
2028
|
-
deactivateChildRoutes(futureNode, currNode, contexts) {
|
|
2029
|
-
const children = nodeChildrenAsMap(currNode);
|
|
2030
|
-
// Recurse on the routes active in the future state to de-activate deeper children
|
|
2031
|
-
futureNode.children.forEach(futureChild => {
|
|
2032
|
-
const childOutletName = futureChild.value.outlet;
|
|
2033
|
-
this.deactivateRoutes(futureChild, children[childOutletName], contexts);
|
|
2034
|
-
delete children[childOutletName];
|
|
2035
|
-
});
|
|
2036
|
-
// De-activate the routes that will not be re-used
|
|
2037
|
-
forEach(children, (v, childName) => {
|
|
2038
|
-
this.deactivateRouteAndItsChildren(v, contexts);
|
|
2039
|
-
});
|
|
2040
|
-
}
|
|
2041
|
-
deactivateRoutes(futureNode, currNode, parentContext) {
|
|
2042
|
-
const future = futureNode.value;
|
|
2043
|
-
const curr = currNode ? currNode.value : null;
|
|
2044
|
-
if (future === curr) {
|
|
2045
|
-
// Reusing the node, check to see if the children need to be de-activated
|
|
2046
|
-
if (future.component) {
|
|
2047
|
-
// If we have a normal route, we need to go through an outlet.
|
|
2048
|
-
const context = parentContext.getContext(future.outlet);
|
|
2049
|
-
if (context) {
|
|
2050
|
-
this.deactivateChildRoutes(futureNode, currNode, context.children);
|
|
2051
|
-
}
|
|
2052
|
-
}
|
|
2053
|
-
else {
|
|
2054
|
-
// if we have a componentless route, we recurse but keep the same outlet map.
|
|
2055
|
-
this.deactivateChildRoutes(futureNode, currNode, parentContext);
|
|
2056
|
-
}
|
|
2057
|
-
}
|
|
2058
|
-
else {
|
|
2059
|
-
if (curr) {
|
|
2060
|
-
// Deactivate the current route which will not be re-used
|
|
2061
|
-
this.deactivateRouteAndItsChildren(currNode, parentContext);
|
|
2062
|
-
}
|
|
2063
|
-
}
|
|
2082
|
+
/**
|
|
2083
|
+
* Store contextual information about a `RouterOutlet`
|
|
2084
|
+
*
|
|
2085
|
+
* @publicApi
|
|
2086
|
+
*/
|
|
2087
|
+
class OutletContext {
|
|
2088
|
+
constructor() {
|
|
2089
|
+
this.outlet = null;
|
|
2090
|
+
this.route = null;
|
|
2091
|
+
/**
|
|
2092
|
+
* @deprecated Passing a resolver to retrieve a component factory is not required and is
|
|
2093
|
+
* deprecated since v14.
|
|
2094
|
+
*/
|
|
2095
|
+
this.resolver = null;
|
|
2096
|
+
this.injector = null;
|
|
2097
|
+
this.children = new ChildrenOutletContexts();
|
|
2098
|
+
this.attachRef = null;
|
|
2064
2099
|
}
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2100
|
+
}
|
|
2101
|
+
/**
|
|
2102
|
+
* Store contextual information about the children (= nested) `RouterOutlet`
|
|
2103
|
+
*
|
|
2104
|
+
* @publicApi
|
|
2105
|
+
*/
|
|
2106
|
+
class ChildrenOutletContexts {
|
|
2107
|
+
constructor() {
|
|
2108
|
+
// contexts for child outlets, by name.
|
|
2109
|
+
this.contexts = new Map();
|
|
2074
2110
|
}
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
const
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
this.deactivateRouteAndItsChildren(children[childOutlet], contexts);
|
|
2081
|
-
}
|
|
2082
|
-
if (context && context.outlet) {
|
|
2083
|
-
const componentRef = context.outlet.detach();
|
|
2084
|
-
const contexts = context.children.onOutletDeactivated();
|
|
2085
|
-
this.routeReuseStrategy.store(route.value.snapshot, { componentRef, route, contexts });
|
|
2086
|
-
}
|
|
2111
|
+
/** Called when a `RouterOutlet` directive is instantiated */
|
|
2112
|
+
onChildOutletCreated(childName, outlet) {
|
|
2113
|
+
const context = this.getOrCreateContext(childName);
|
|
2114
|
+
context.outlet = outlet;
|
|
2115
|
+
this.contexts.set(childName, context);
|
|
2087
2116
|
}
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
if (context && context.outlet) {
|
|
2098
|
-
// Destroy the component
|
|
2099
|
-
context.outlet.deactivate();
|
|
2100
|
-
// Destroy the contexts for all the outlets that were in the component
|
|
2101
|
-
context.children.onOutletDeactivated();
|
|
2102
|
-
// Clear the information about the attached component on the context but keep the reference to
|
|
2103
|
-
// the outlet.
|
|
2117
|
+
/**
|
|
2118
|
+
* Called when a `RouterOutlet` directive is destroyed.
|
|
2119
|
+
* We need to keep the context as the outlet could be destroyed inside a NgIf and might be
|
|
2120
|
+
* re-created later.
|
|
2121
|
+
*/
|
|
2122
|
+
onChildOutletDestroyed(childName) {
|
|
2123
|
+
const context = this.getContext(childName);
|
|
2124
|
+
if (context) {
|
|
2125
|
+
context.outlet = null;
|
|
2104
2126
|
context.attachRef = null;
|
|
2105
|
-
context.resolver = null;
|
|
2106
|
-
context.route = null;
|
|
2107
2127
|
}
|
|
2108
2128
|
}
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
}
|
|
2129
|
+
/**
|
|
2130
|
+
* Called when the corresponding route is deactivated during navigation.
|
|
2131
|
+
* Because the component get destroyed, all children outlet are destroyed.
|
|
2132
|
+
*/
|
|
2133
|
+
onOutletDeactivated() {
|
|
2134
|
+
const contexts = this.contexts;
|
|
2135
|
+
this.contexts = new Map();
|
|
2136
|
+
return contexts;
|
|
2118
2137
|
}
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
if (
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
const context = parentContexts.getOrCreateContext(future.outlet);
|
|
2128
|
-
this.activateChildRoutes(futureNode, currNode, context.children);
|
|
2129
|
-
}
|
|
2130
|
-
else {
|
|
2131
|
-
// if we have a componentless route, we recurse but keep the same outlet map.
|
|
2132
|
-
this.activateChildRoutes(futureNode, currNode, parentContexts);
|
|
2133
|
-
}
|
|
2134
|
-
}
|
|
2135
|
-
else {
|
|
2136
|
-
if (future.component) {
|
|
2137
|
-
// if we have a normal route, we need to place the component into the outlet and recurse.
|
|
2138
|
-
const context = parentContexts.getOrCreateContext(future.outlet);
|
|
2139
|
-
if (this.routeReuseStrategy.shouldAttach(future.snapshot)) {
|
|
2140
|
-
const stored = this.routeReuseStrategy.retrieve(future.snapshot);
|
|
2141
|
-
this.routeReuseStrategy.store(future.snapshot, null);
|
|
2142
|
-
context.children.onOutletReAttached(stored.contexts);
|
|
2143
|
-
context.attachRef = stored.componentRef;
|
|
2144
|
-
context.route = stored.route.value;
|
|
2145
|
-
if (context.outlet) {
|
|
2146
|
-
// Attach right away when the outlet has already been instantiated
|
|
2147
|
-
// Otherwise attach from `RouterOutlet.ngOnInit` when it is instantiated
|
|
2148
|
-
context.outlet.attach(stored.componentRef, stored.route.value);
|
|
2149
|
-
}
|
|
2150
|
-
advanceActivatedRoute(stored.route.value);
|
|
2151
|
-
this.activateChildRoutes(futureNode, null, context.children);
|
|
2152
|
-
}
|
|
2153
|
-
else {
|
|
2154
|
-
const config = parentLoadedConfig(future.snapshot);
|
|
2155
|
-
const cmpFactoryResolver = config ? config.module.componentFactoryResolver : null;
|
|
2156
|
-
context.attachRef = null;
|
|
2157
|
-
context.route = future;
|
|
2158
|
-
context.resolver = cmpFactoryResolver;
|
|
2159
|
-
if (context.outlet) {
|
|
2160
|
-
// Activate the outlet when it has already been instantiated
|
|
2161
|
-
// Otherwise it will get activated from its `ngOnInit` when instantiated
|
|
2162
|
-
context.outlet.activateWith(future, cmpFactoryResolver);
|
|
2163
|
-
}
|
|
2164
|
-
this.activateChildRoutes(futureNode, null, context.children);
|
|
2165
|
-
}
|
|
2166
|
-
}
|
|
2167
|
-
else {
|
|
2168
|
-
// if we have a componentless route, we recurse but keep the same outlet map.
|
|
2169
|
-
this.activateChildRoutes(futureNode, null, parentContexts);
|
|
2170
|
-
}
|
|
2138
|
+
onOutletReAttached(contexts) {
|
|
2139
|
+
this.contexts = contexts;
|
|
2140
|
+
}
|
|
2141
|
+
getOrCreateContext(childName) {
|
|
2142
|
+
let context = this.getContext(childName);
|
|
2143
|
+
if (!context) {
|
|
2144
|
+
context = new OutletContext();
|
|
2145
|
+
this.contexts.set(childName, context);
|
|
2171
2146
|
}
|
|
2147
|
+
return context;
|
|
2172
2148
|
}
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
for (let s = snapshot.parent; s; s = s.parent) {
|
|
2176
|
-
const route = s.routeConfig;
|
|
2177
|
-
if (route && route._loadedConfig)
|
|
2178
|
-
return route._loadedConfig;
|
|
2179
|
-
if (route && route.component)
|
|
2180
|
-
return null;
|
|
2149
|
+
getContext(childName) {
|
|
2150
|
+
return this.contexts.get(childName) || null;
|
|
2181
2151
|
}
|
|
2182
|
-
return null;
|
|
2183
2152
|
}
|
|
2184
2153
|
|
|
2185
2154
|
/**
|
|
@@ -2189,182 +2158,13 @@ function parentLoadedConfig(snapshot) {
|
|
|
2189
2158
|
* Use of this source code is governed by an MIT-style license that can be
|
|
2190
2159
|
* found in the LICENSE file at https://angular.io/license
|
|
2191
2160
|
*/
|
|
2192
|
-
class LoadedRouterConfig {
|
|
2193
|
-
constructor(routes, module) {
|
|
2194
|
-
this.routes = routes;
|
|
2195
|
-
this.module = module;
|
|
2196
|
-
}
|
|
2197
|
-
}
|
|
2198
|
-
|
|
2199
2161
|
/**
|
|
2200
|
-
* @
|
|
2201
|
-
* Copyright Google LLC All Rights Reserved.
|
|
2162
|
+
* @description
|
|
2202
2163
|
*
|
|
2203
|
-
*
|
|
2204
|
-
* found in the LICENSE file at https://angular.io/license
|
|
2205
|
-
*/
|
|
2206
|
-
/**
|
|
2207
|
-
* Simple function check, but generic so type inference will flow. Example:
|
|
2164
|
+
* Acts as a placeholder that Angular dynamically fills based on the current router state.
|
|
2208
2165
|
*
|
|
2209
|
-
*
|
|
2210
|
-
*
|
|
2211
|
-
* }
|
|
2212
|
-
*
|
|
2213
|
-
* if (isFunction<product>(fn)) {
|
|
2214
|
-
* return fn(1, 2);
|
|
2215
|
-
* } else {
|
|
2216
|
-
* throw "Must provide the `product` function";
|
|
2217
|
-
* }
|
|
2218
|
-
*/
|
|
2219
|
-
function isFunction(v) {
|
|
2220
|
-
return typeof v === 'function';
|
|
2221
|
-
}
|
|
2222
|
-
function isBoolean(v) {
|
|
2223
|
-
return typeof v === 'boolean';
|
|
2224
|
-
}
|
|
2225
|
-
function isUrlTree(v) {
|
|
2226
|
-
return v instanceof UrlTree;
|
|
2227
|
-
}
|
|
2228
|
-
function isCanLoad(guard) {
|
|
2229
|
-
return guard && isFunction(guard.canLoad);
|
|
2230
|
-
}
|
|
2231
|
-
function isCanActivate(guard) {
|
|
2232
|
-
return guard && isFunction(guard.canActivate);
|
|
2233
|
-
}
|
|
2234
|
-
function isCanActivateChild(guard) {
|
|
2235
|
-
return guard && isFunction(guard.canActivateChild);
|
|
2236
|
-
}
|
|
2237
|
-
function isCanDeactivate(guard) {
|
|
2238
|
-
return guard && isFunction(guard.canDeactivate);
|
|
2239
|
-
}
|
|
2240
|
-
|
|
2241
|
-
/**
|
|
2242
|
-
* @license
|
|
2243
|
-
* Copyright Google LLC All Rights Reserved.
|
|
2244
|
-
*
|
|
2245
|
-
* Use of this source code is governed by an MIT-style license that can be
|
|
2246
|
-
* found in the LICENSE file at https://angular.io/license
|
|
2247
|
-
*/
|
|
2248
|
-
const INITIAL_VALUE = Symbol('INITIAL_VALUE');
|
|
2249
|
-
function prioritizedGuardValue() {
|
|
2250
|
-
return switchMap(obs => {
|
|
2251
|
-
return combineLatest(obs.map(o => o.pipe(take(1), startWith(INITIAL_VALUE))))
|
|
2252
|
-
.pipe(scan((acc, list) => {
|
|
2253
|
-
let isPending = false;
|
|
2254
|
-
return list.reduce((innerAcc, val, i) => {
|
|
2255
|
-
if (innerAcc !== INITIAL_VALUE)
|
|
2256
|
-
return innerAcc;
|
|
2257
|
-
// Toggle pending flag if any values haven't been set yet
|
|
2258
|
-
if (val === INITIAL_VALUE)
|
|
2259
|
-
isPending = true;
|
|
2260
|
-
// Any other return values are only valid if we haven't yet hit a pending
|
|
2261
|
-
// call. This guarantees that in the case of a guard at the bottom of the
|
|
2262
|
-
// tree that returns a redirect, we will wait for the higher priority
|
|
2263
|
-
// guard at the top to finish before performing the redirect.
|
|
2264
|
-
if (!isPending) {
|
|
2265
|
-
// Early return when we hit a `false` value as that should always
|
|
2266
|
-
// cancel navigation
|
|
2267
|
-
if (val === false)
|
|
2268
|
-
return val;
|
|
2269
|
-
if (i === list.length - 1 || isUrlTree(val)) {
|
|
2270
|
-
return val;
|
|
2271
|
-
}
|
|
2272
|
-
}
|
|
2273
|
-
return innerAcc;
|
|
2274
|
-
}, acc);
|
|
2275
|
-
}, INITIAL_VALUE), filter(item => item !== INITIAL_VALUE), map(item => isUrlTree(item) ? item : item === true), //
|
|
2276
|
-
take(1));
|
|
2277
|
-
});
|
|
2278
|
-
}
|
|
2279
|
-
|
|
2280
|
-
/**
|
|
2281
|
-
* @license
|
|
2282
|
-
* Copyright Google LLC All Rights Reserved.
|
|
2283
|
-
*
|
|
2284
|
-
* Use of this source code is governed by an MIT-style license that can be
|
|
2285
|
-
* found in the LICENSE file at https://angular.io/license
|
|
2286
|
-
*/
|
|
2287
|
-
/**
|
|
2288
|
-
* Store contextual information about a `RouterOutlet`
|
|
2289
|
-
*
|
|
2290
|
-
* @publicApi
|
|
2291
|
-
*/
|
|
2292
|
-
class OutletContext {
|
|
2293
|
-
constructor() {
|
|
2294
|
-
this.outlet = null;
|
|
2295
|
-
this.route = null;
|
|
2296
|
-
this.resolver = null;
|
|
2297
|
-
this.children = new ChildrenOutletContexts();
|
|
2298
|
-
this.attachRef = null;
|
|
2299
|
-
}
|
|
2300
|
-
}
|
|
2301
|
-
/**
|
|
2302
|
-
* Store contextual information about the children (= nested) `RouterOutlet`
|
|
2303
|
-
*
|
|
2304
|
-
* @publicApi
|
|
2305
|
-
*/
|
|
2306
|
-
class ChildrenOutletContexts {
|
|
2307
|
-
constructor() {
|
|
2308
|
-
// contexts for child outlets, by name.
|
|
2309
|
-
this.contexts = new Map();
|
|
2310
|
-
}
|
|
2311
|
-
/** Called when a `RouterOutlet` directive is instantiated */
|
|
2312
|
-
onChildOutletCreated(childName, outlet) {
|
|
2313
|
-
const context = this.getOrCreateContext(childName);
|
|
2314
|
-
context.outlet = outlet;
|
|
2315
|
-
this.contexts.set(childName, context);
|
|
2316
|
-
}
|
|
2317
|
-
/**
|
|
2318
|
-
* Called when a `RouterOutlet` directive is destroyed.
|
|
2319
|
-
* We need to keep the context as the outlet could be destroyed inside a NgIf and might be
|
|
2320
|
-
* re-created later.
|
|
2321
|
-
*/
|
|
2322
|
-
onChildOutletDestroyed(childName) {
|
|
2323
|
-
const context = this.getContext(childName);
|
|
2324
|
-
if (context) {
|
|
2325
|
-
context.outlet = null;
|
|
2326
|
-
context.attachRef = null;
|
|
2327
|
-
}
|
|
2328
|
-
}
|
|
2329
|
-
/**
|
|
2330
|
-
* Called when the corresponding route is deactivated during navigation.
|
|
2331
|
-
* Because the component get destroyed, all children outlet are destroyed.
|
|
2332
|
-
*/
|
|
2333
|
-
onOutletDeactivated() {
|
|
2334
|
-
const contexts = this.contexts;
|
|
2335
|
-
this.contexts = new Map();
|
|
2336
|
-
return contexts;
|
|
2337
|
-
}
|
|
2338
|
-
onOutletReAttached(contexts) {
|
|
2339
|
-
this.contexts = contexts;
|
|
2340
|
-
}
|
|
2341
|
-
getOrCreateContext(childName) {
|
|
2342
|
-
let context = this.getContext(childName);
|
|
2343
|
-
if (!context) {
|
|
2344
|
-
context = new OutletContext();
|
|
2345
|
-
this.contexts.set(childName, context);
|
|
2346
|
-
}
|
|
2347
|
-
return context;
|
|
2348
|
-
}
|
|
2349
|
-
getContext(childName) {
|
|
2350
|
-
return this.contexts.get(childName) || null;
|
|
2351
|
-
}
|
|
2352
|
-
}
|
|
2353
|
-
|
|
2354
|
-
/**
|
|
2355
|
-
* @license
|
|
2356
|
-
* Copyright Google LLC All Rights Reserved.
|
|
2357
|
-
*
|
|
2358
|
-
* Use of this source code is governed by an MIT-style license that can be
|
|
2359
|
-
* found in the LICENSE file at https://angular.io/license
|
|
2360
|
-
*/
|
|
2361
|
-
/**
|
|
2362
|
-
* @description
|
|
2363
|
-
*
|
|
2364
|
-
* Acts as a placeholder that Angular dynamically fills based on the current router state.
|
|
2365
|
-
*
|
|
2366
|
-
* Each outlet can have a unique name, determined by the optional `name` attribute.
|
|
2367
|
-
* The name cannot be set or changed dynamically. If not set, default value is "primary".
|
|
2166
|
+
* Each outlet can have a unique name, determined by the optional `name` attribute.
|
|
2167
|
+
* The name cannot be set or changed dynamically. If not set, default value is "primary".
|
|
2368
2168
|
*
|
|
2369
2169
|
* ```
|
|
2370
2170
|
* <router-outlet></router-outlet>
|
|
@@ -2410,11 +2210,11 @@ class ChildrenOutletContexts {
|
|
|
2410
2210
|
* @publicApi
|
|
2411
2211
|
*/
|
|
2412
2212
|
class RouterOutlet {
|
|
2413
|
-
constructor(parentContexts, location,
|
|
2213
|
+
constructor(parentContexts, location, name, changeDetector, environmentInjector) {
|
|
2414
2214
|
this.parentContexts = parentContexts;
|
|
2415
2215
|
this.location = location;
|
|
2416
|
-
this.resolver = resolver;
|
|
2417
2216
|
this.changeDetector = changeDetector;
|
|
2217
|
+
this.environmentInjector = environmentInjector;
|
|
2418
2218
|
this.activated = null;
|
|
2419
2219
|
this._activatedRoute = null;
|
|
2420
2220
|
this.activateEvents = new EventEmitter();
|
|
@@ -2449,7 +2249,7 @@ class RouterOutlet {
|
|
|
2449
2249
|
}
|
|
2450
2250
|
else {
|
|
2451
2251
|
// otherwise the component defined in the configuration is created
|
|
2452
|
-
this.activateWith(context.route, context.
|
|
2252
|
+
this.activateWith(context.route, context.injector);
|
|
2453
2253
|
}
|
|
2454
2254
|
}
|
|
2455
2255
|
}
|
|
@@ -2508,34 +2308,40 @@ class RouterOutlet {
|
|
|
2508
2308
|
this.deactivateEvents.emit(c);
|
|
2509
2309
|
}
|
|
2510
2310
|
}
|
|
2511
|
-
activateWith(activatedRoute,
|
|
2311
|
+
activateWith(activatedRoute, resolverOrInjector) {
|
|
2512
2312
|
if (this.isActivated) {
|
|
2513
2313
|
throw new Error('Cannot activate an already activated outlet');
|
|
2514
2314
|
}
|
|
2515
2315
|
this._activatedRoute = activatedRoute;
|
|
2316
|
+
const location = this.location;
|
|
2516
2317
|
const snapshot = activatedRoute._futureSnapshot;
|
|
2517
|
-
const component = snapshot.
|
|
2518
|
-
resolver = resolver || this.resolver;
|
|
2519
|
-
const factory = resolver.resolveComponentFactory(component);
|
|
2318
|
+
const component = snapshot.component;
|
|
2520
2319
|
const childContexts = this.parentContexts.getOrCreateContext(this.name).children;
|
|
2521
|
-
const injector = new OutletInjector(activatedRoute, childContexts,
|
|
2522
|
-
|
|
2320
|
+
const injector = new OutletInjector(activatedRoute, childContexts, location.injector);
|
|
2321
|
+
if (resolverOrInjector && isComponentFactoryResolver(resolverOrInjector)) {
|
|
2322
|
+
const factory = resolverOrInjector.resolveComponentFactory(component);
|
|
2323
|
+
this.activated = location.createComponent(factory, location.length, injector);
|
|
2324
|
+
}
|
|
2325
|
+
else {
|
|
2326
|
+
const environmentInjector = resolverOrInjector !== null && resolverOrInjector !== void 0 ? resolverOrInjector : this.environmentInjector;
|
|
2327
|
+
this.activated = location.createComponent(component, { index: location.length, injector, environmentInjector });
|
|
2328
|
+
}
|
|
2523
2329
|
// Calling `markForCheck` to make sure we will run the change detection when the
|
|
2524
2330
|
// `RouterOutlet` is inside a `ChangeDetectionStrategy.OnPush` component.
|
|
2525
2331
|
this.changeDetector.markForCheck();
|
|
2526
2332
|
this.activateEvents.emit(this.activated.instance);
|
|
2527
2333
|
}
|
|
2528
2334
|
}
|
|
2529
|
-
RouterOutlet.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-
|
|
2530
|
-
RouterOutlet.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "
|
|
2531
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-
|
|
2335
|
+
RouterOutlet.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterOutlet, deps: [{ token: ChildrenOutletContexts }, { token: i0.ViewContainerRef }, { token: 'name', attribute: true }, { token: i0.ChangeDetectorRef }, { token: i0.EnvironmentInjector }], target: i0.ɵɵFactoryTarget.Directive });
|
|
2336
|
+
RouterOutlet.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.0.0-rc.2", type: RouterOutlet, selector: "router-outlet", outputs: { activateEvents: "activate", deactivateEvents: "deactivate", attachEvents: "attach", detachEvents: "detach" }, exportAs: ["outlet"], ngImport: i0 });
|
|
2337
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterOutlet, decorators: [{
|
|
2532
2338
|
type: Directive,
|
|
2533
2339
|
args: [{ selector: 'router-outlet', exportAs: 'outlet' }]
|
|
2534
2340
|
}], ctorParameters: function () {
|
|
2535
|
-
return [{ type: ChildrenOutletContexts }, { type: i0.ViewContainerRef }, { type:
|
|
2341
|
+
return [{ type: ChildrenOutletContexts }, { type: i0.ViewContainerRef }, { type: undefined, decorators: [{
|
|
2536
2342
|
type: Attribute,
|
|
2537
2343
|
args: ['name']
|
|
2538
|
-
}] }, { type: i0.ChangeDetectorRef }];
|
|
2344
|
+
}] }, { type: i0.ChangeDetectorRef }, { type: i0.EnvironmentInjector }];
|
|
2539
2345
|
}, propDecorators: { activateEvents: [{
|
|
2540
2346
|
type: Output,
|
|
2541
2347
|
args: ['activate']
|
|
@@ -2562,7 +2368,403 @@ class OutletInjector {
|
|
|
2562
2368
|
if (token === ChildrenOutletContexts) {
|
|
2563
2369
|
return this.childContexts;
|
|
2564
2370
|
}
|
|
2565
|
-
return this.parent.get(token, notFoundValue);
|
|
2371
|
+
return this.parent.get(token, notFoundValue);
|
|
2372
|
+
}
|
|
2373
|
+
}
|
|
2374
|
+
function isComponentFactoryResolver(item) {
|
|
2375
|
+
return !!item.resolveComponentFactory;
|
|
2376
|
+
}
|
|
2377
|
+
|
|
2378
|
+
/**
|
|
2379
|
+
* @license
|
|
2380
|
+
* Copyright Google LLC All Rights Reserved.
|
|
2381
|
+
*
|
|
2382
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
2383
|
+
* found in the LICENSE file at https://angular.io/license
|
|
2384
|
+
*/
|
|
2385
|
+
/**
|
|
2386
|
+
* This component is used internally within the router to be a placeholder when an empty
|
|
2387
|
+
* router-outlet is needed. For example, with a config such as:
|
|
2388
|
+
*
|
|
2389
|
+
* `{path: 'parent', outlet: 'nav', children: [...]}`
|
|
2390
|
+
*
|
|
2391
|
+
* In order to render, there needs to be a component on this config, which will default
|
|
2392
|
+
* to this `EmptyOutletComponent`.
|
|
2393
|
+
*/
|
|
2394
|
+
class ɵEmptyOutletComponent {
|
|
2395
|
+
}
|
|
2396
|
+
ɵEmptyOutletComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: ɵEmptyOutletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2397
|
+
ɵEmptyOutletComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.0-rc.2", 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"] }] });
|
|
2398
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: ɵEmptyOutletComponent, decorators: [{
|
|
2399
|
+
type: Component,
|
|
2400
|
+
args: [{ template: `<router-outlet></router-outlet>` }]
|
|
2401
|
+
}] });
|
|
2402
|
+
|
|
2403
|
+
/**
|
|
2404
|
+
* @license
|
|
2405
|
+
* Copyright Google LLC All Rights Reserved.
|
|
2406
|
+
*
|
|
2407
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
2408
|
+
* found in the LICENSE file at https://angular.io/license
|
|
2409
|
+
*/
|
|
2410
|
+
/**
|
|
2411
|
+
* Creates an `EnvironmentInjector` if the `Route` has providers and one does not already exist
|
|
2412
|
+
* and returns the injector. Otherwise, if the `Route` does not have `providers`, returns the
|
|
2413
|
+
* `currentInjector`.
|
|
2414
|
+
*
|
|
2415
|
+
* @param route The route that might have providers
|
|
2416
|
+
* @param currentInjector The parent injector of the `Route`
|
|
2417
|
+
*/
|
|
2418
|
+
function getOrCreateRouteInjectorIfNeeded(route, currentInjector) {
|
|
2419
|
+
var _a;
|
|
2420
|
+
if (route.providers && !route._injector) {
|
|
2421
|
+
route._injector =
|
|
2422
|
+
createEnvironmentInjector(route.providers, currentInjector, `Route: ${route.path}`);
|
|
2423
|
+
}
|
|
2424
|
+
return (_a = route._injector) !== null && _a !== void 0 ? _a : currentInjector;
|
|
2425
|
+
}
|
|
2426
|
+
function getLoadedRoutes(route) {
|
|
2427
|
+
return route._loadedRoutes;
|
|
2428
|
+
}
|
|
2429
|
+
function getLoadedInjector(route) {
|
|
2430
|
+
return route._loadedInjector;
|
|
2431
|
+
}
|
|
2432
|
+
function getLoadedComponent(route) {
|
|
2433
|
+
return route._loadedComponent;
|
|
2434
|
+
}
|
|
2435
|
+
function getProvidersInjector(route) {
|
|
2436
|
+
return route._injector;
|
|
2437
|
+
}
|
|
2438
|
+
function validateConfig(config, parentPath = '', requireStandaloneComponents = false) {
|
|
2439
|
+
// forEach doesn't iterate undefined values
|
|
2440
|
+
for (let i = 0; i < config.length; i++) {
|
|
2441
|
+
const route = config[i];
|
|
2442
|
+
const fullPath = getFullPath(parentPath, route);
|
|
2443
|
+
validateNode(route, fullPath, requireStandaloneComponents);
|
|
2444
|
+
}
|
|
2445
|
+
}
|
|
2446
|
+
function assertStandalone(fullPath, component) {
|
|
2447
|
+
if (component && !ɵisStandalone(component)) {
|
|
2448
|
+
throw new Error(`Invalid configuration of route '${fullPath}'. The component must be standalone.`);
|
|
2449
|
+
}
|
|
2450
|
+
}
|
|
2451
|
+
function validateNode(route, fullPath, requireStandaloneComponents) {
|
|
2452
|
+
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
2453
|
+
if (!route) {
|
|
2454
|
+
throw new Error(`
|
|
2455
|
+
Invalid configuration of route '${fullPath}': Encountered undefined route.
|
|
2456
|
+
The reason might be an extra comma.
|
|
2457
|
+
|
|
2458
|
+
Example:
|
|
2459
|
+
const routes: Routes = [
|
|
2460
|
+
{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },
|
|
2461
|
+
{ path: 'dashboard', component: DashboardComponent },, << two commas
|
|
2462
|
+
{ path: 'detail/:id', component: HeroDetailComponent }
|
|
2463
|
+
];
|
|
2464
|
+
`);
|
|
2465
|
+
}
|
|
2466
|
+
if (Array.isArray(route)) {
|
|
2467
|
+
throw new Error(`Invalid configuration of route '${fullPath}': Array cannot be specified`);
|
|
2468
|
+
}
|
|
2469
|
+
if (!route.component && !route.loadComponent && !route.children && !route.loadChildren &&
|
|
2470
|
+
(route.outlet && route.outlet !== PRIMARY_OUTLET)) {
|
|
2471
|
+
throw new Error(`Invalid configuration of route '${fullPath}': a componentless route without children or loadChildren cannot have a named outlet set`);
|
|
2472
|
+
}
|
|
2473
|
+
if (route.redirectTo && route.children) {
|
|
2474
|
+
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and children cannot be used together`);
|
|
2475
|
+
}
|
|
2476
|
+
if (route.redirectTo && route.loadChildren) {
|
|
2477
|
+
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and loadChildren cannot be used together`);
|
|
2478
|
+
}
|
|
2479
|
+
if (route.children && route.loadChildren) {
|
|
2480
|
+
throw new Error(`Invalid configuration of route '${fullPath}': children and loadChildren cannot be used together`);
|
|
2481
|
+
}
|
|
2482
|
+
if (route.redirectTo && (route.component || route.loadComponent)) {
|
|
2483
|
+
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and component/loadComponent cannot be used together`);
|
|
2484
|
+
}
|
|
2485
|
+
if (route.component && route.loadComponent) {
|
|
2486
|
+
throw new Error(`Invalid configuration of route '${fullPath}': component and loadComponent cannot be used together`);
|
|
2487
|
+
}
|
|
2488
|
+
if (route.redirectTo && route.canActivate) {
|
|
2489
|
+
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and canActivate cannot be used together. Redirects happen before activation ` +
|
|
2490
|
+
`so canActivate will never be executed.`);
|
|
2491
|
+
}
|
|
2492
|
+
if (route.path && route.matcher) {
|
|
2493
|
+
throw new Error(`Invalid configuration of route '${fullPath}': path and matcher cannot be used together`);
|
|
2494
|
+
}
|
|
2495
|
+
if (route.redirectTo === void 0 && !route.component && !route.loadComponent &&
|
|
2496
|
+
!route.children && !route.loadChildren) {
|
|
2497
|
+
throw new Error(`Invalid configuration of route '${fullPath}'. One of the following must be provided: component, loadComponent, redirectTo, children or loadChildren`);
|
|
2498
|
+
}
|
|
2499
|
+
if (route.path === void 0 && route.matcher === void 0) {
|
|
2500
|
+
throw new Error(`Invalid configuration of route '${fullPath}': routes must have either a path or a matcher specified`);
|
|
2501
|
+
}
|
|
2502
|
+
if (typeof route.path === 'string' && route.path.charAt(0) === '/') {
|
|
2503
|
+
throw new Error(`Invalid configuration of route '${fullPath}': path cannot start with a slash`);
|
|
2504
|
+
}
|
|
2505
|
+
if (route.path === '' && route.redirectTo !== void 0 && route.pathMatch === void 0) {
|
|
2506
|
+
const exp = `The default value of 'pathMatch' is 'prefix', but often the intent is to use 'full'.`;
|
|
2507
|
+
throw new Error(`Invalid configuration of route '{path: "${fullPath}", redirectTo: "${route.redirectTo}"}': please provide 'pathMatch'. ${exp}`);
|
|
2508
|
+
}
|
|
2509
|
+
if (requireStandaloneComponents) {
|
|
2510
|
+
assertStandalone(fullPath, route.component);
|
|
2511
|
+
}
|
|
2512
|
+
}
|
|
2513
|
+
if (route.children) {
|
|
2514
|
+
validateConfig(route.children, fullPath, requireStandaloneComponents);
|
|
2515
|
+
}
|
|
2516
|
+
}
|
|
2517
|
+
function getFullPath(parentPath, currentRoute) {
|
|
2518
|
+
if (!currentRoute) {
|
|
2519
|
+
return parentPath;
|
|
2520
|
+
}
|
|
2521
|
+
if (!parentPath && !currentRoute.path) {
|
|
2522
|
+
return '';
|
|
2523
|
+
}
|
|
2524
|
+
else if (parentPath && !currentRoute.path) {
|
|
2525
|
+
return `${parentPath}/`;
|
|
2526
|
+
}
|
|
2527
|
+
else if (!parentPath && currentRoute.path) {
|
|
2528
|
+
return currentRoute.path;
|
|
2529
|
+
}
|
|
2530
|
+
else {
|
|
2531
|
+
return `${parentPath}/${currentRoute.path}`;
|
|
2532
|
+
}
|
|
2533
|
+
}
|
|
2534
|
+
/**
|
|
2535
|
+
* Makes a copy of the config and adds any default required properties.
|
|
2536
|
+
*/
|
|
2537
|
+
function standardizeConfig(r) {
|
|
2538
|
+
const children = r.children && r.children.map(standardizeConfig);
|
|
2539
|
+
const c = children ? Object.assign(Object.assign({}, r), { children }) : Object.assign({}, r);
|
|
2540
|
+
if ((!c.component && !c.loadComponent) && (children || c.loadChildren) &&
|
|
2541
|
+
(c.outlet && c.outlet !== PRIMARY_OUTLET)) {
|
|
2542
|
+
c.component = ɵEmptyOutletComponent;
|
|
2543
|
+
}
|
|
2544
|
+
return c;
|
|
2545
|
+
}
|
|
2546
|
+
/** Returns the `route.outlet` or PRIMARY_OUTLET if none exists. */
|
|
2547
|
+
function getOutlet(route) {
|
|
2548
|
+
return route.outlet || PRIMARY_OUTLET;
|
|
2549
|
+
}
|
|
2550
|
+
/**
|
|
2551
|
+
* Sorts the `routes` such that the ones with an outlet matching `outletName` come first.
|
|
2552
|
+
* The order of the configs is otherwise preserved.
|
|
2553
|
+
*/
|
|
2554
|
+
function sortByMatchingOutlets(routes, outletName) {
|
|
2555
|
+
const sortedConfig = routes.filter(r => getOutlet(r) === outletName);
|
|
2556
|
+
sortedConfig.push(...routes.filter(r => getOutlet(r) !== outletName));
|
|
2557
|
+
return sortedConfig;
|
|
2558
|
+
}
|
|
2559
|
+
/**
|
|
2560
|
+
* Gets the first injector in the snapshot's parent tree.
|
|
2561
|
+
*
|
|
2562
|
+
* If the `Route` has a static list of providers, the returned injector will be the one created from
|
|
2563
|
+
* those. If it does not exist, the returned injector may come from the parents, which may be from a
|
|
2564
|
+
* loaded config or their static providers.
|
|
2565
|
+
*
|
|
2566
|
+
* Returns `null` if there is neither this nor any parents have a stored injector.
|
|
2567
|
+
*
|
|
2568
|
+
* Generally used for retrieving the injector to use for getting tokens for guards/resolvers and
|
|
2569
|
+
* also used for getting the correct injector to use for creating components.
|
|
2570
|
+
*/
|
|
2571
|
+
function getClosestRouteInjector(snapshot) {
|
|
2572
|
+
var _a;
|
|
2573
|
+
if (!snapshot)
|
|
2574
|
+
return null;
|
|
2575
|
+
// If the current route has its own injector, which is created from the static providers on the
|
|
2576
|
+
// route itself, we should use that. Otherwise, we start at the parent since we do not want to
|
|
2577
|
+
// include the lazy loaded injector from this route.
|
|
2578
|
+
if ((_a = snapshot.routeConfig) === null || _a === void 0 ? void 0 : _a._injector) {
|
|
2579
|
+
return snapshot.routeConfig._injector;
|
|
2580
|
+
}
|
|
2581
|
+
for (let s = snapshot.parent; s; s = s.parent) {
|
|
2582
|
+
const route = s.routeConfig;
|
|
2583
|
+
// Note that the order here is important. `_loadedInjector` stored on the route with
|
|
2584
|
+
// `loadChildren: () => NgModule` so it applies to child routes with priority. The `_injector`
|
|
2585
|
+
// is created from the static providers on that parent route, so it applies to the children as
|
|
2586
|
+
// well, but only if there is no lazy loaded NgModuleRef injector.
|
|
2587
|
+
if (route === null || route === void 0 ? void 0 : route._loadedInjector)
|
|
2588
|
+
return route._loadedInjector;
|
|
2589
|
+
if (route === null || route === void 0 ? void 0 : route._injector)
|
|
2590
|
+
return route._injector;
|
|
2591
|
+
}
|
|
2592
|
+
return null;
|
|
2593
|
+
}
|
|
2594
|
+
|
|
2595
|
+
/**
|
|
2596
|
+
* @license
|
|
2597
|
+
* Copyright Google LLC All Rights Reserved.
|
|
2598
|
+
*
|
|
2599
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
2600
|
+
* found in the LICENSE file at https://angular.io/license
|
|
2601
|
+
*/
|
|
2602
|
+
const activateRoutes = (rootContexts, routeReuseStrategy, forwardEvent) => map(t => {
|
|
2603
|
+
new ActivateRoutes(routeReuseStrategy, t.targetRouterState, t.currentRouterState, forwardEvent)
|
|
2604
|
+
.activate(rootContexts);
|
|
2605
|
+
return t;
|
|
2606
|
+
});
|
|
2607
|
+
class ActivateRoutes {
|
|
2608
|
+
constructor(routeReuseStrategy, futureState, currState, forwardEvent) {
|
|
2609
|
+
this.routeReuseStrategy = routeReuseStrategy;
|
|
2610
|
+
this.futureState = futureState;
|
|
2611
|
+
this.currState = currState;
|
|
2612
|
+
this.forwardEvent = forwardEvent;
|
|
2613
|
+
}
|
|
2614
|
+
activate(parentContexts) {
|
|
2615
|
+
const futureRoot = this.futureState._root;
|
|
2616
|
+
const currRoot = this.currState ? this.currState._root : null;
|
|
2617
|
+
this.deactivateChildRoutes(futureRoot, currRoot, parentContexts);
|
|
2618
|
+
advanceActivatedRoute(this.futureState.root);
|
|
2619
|
+
this.activateChildRoutes(futureRoot, currRoot, parentContexts);
|
|
2620
|
+
}
|
|
2621
|
+
// De-activate the child route that are not re-used for the future state
|
|
2622
|
+
deactivateChildRoutes(futureNode, currNode, contexts) {
|
|
2623
|
+
const children = nodeChildrenAsMap(currNode);
|
|
2624
|
+
// Recurse on the routes active in the future state to de-activate deeper children
|
|
2625
|
+
futureNode.children.forEach(futureChild => {
|
|
2626
|
+
const childOutletName = futureChild.value.outlet;
|
|
2627
|
+
this.deactivateRoutes(futureChild, children[childOutletName], contexts);
|
|
2628
|
+
delete children[childOutletName];
|
|
2629
|
+
});
|
|
2630
|
+
// De-activate the routes that will not be re-used
|
|
2631
|
+
forEach(children, (v, childName) => {
|
|
2632
|
+
this.deactivateRouteAndItsChildren(v, contexts);
|
|
2633
|
+
});
|
|
2634
|
+
}
|
|
2635
|
+
deactivateRoutes(futureNode, currNode, parentContext) {
|
|
2636
|
+
const future = futureNode.value;
|
|
2637
|
+
const curr = currNode ? currNode.value : null;
|
|
2638
|
+
if (future === curr) {
|
|
2639
|
+
// Reusing the node, check to see if the children need to be de-activated
|
|
2640
|
+
if (future.component) {
|
|
2641
|
+
// If we have a normal route, we need to go through an outlet.
|
|
2642
|
+
const context = parentContext.getContext(future.outlet);
|
|
2643
|
+
if (context) {
|
|
2644
|
+
this.deactivateChildRoutes(futureNode, currNode, context.children);
|
|
2645
|
+
}
|
|
2646
|
+
}
|
|
2647
|
+
else {
|
|
2648
|
+
// if we have a componentless route, we recurse but keep the same outlet map.
|
|
2649
|
+
this.deactivateChildRoutes(futureNode, currNode, parentContext);
|
|
2650
|
+
}
|
|
2651
|
+
}
|
|
2652
|
+
else {
|
|
2653
|
+
if (curr) {
|
|
2654
|
+
// Deactivate the current route which will not be re-used
|
|
2655
|
+
this.deactivateRouteAndItsChildren(currNode, parentContext);
|
|
2656
|
+
}
|
|
2657
|
+
}
|
|
2658
|
+
}
|
|
2659
|
+
deactivateRouteAndItsChildren(route, parentContexts) {
|
|
2660
|
+
// If there is no component, the Route is never attached to an outlet (because there is no
|
|
2661
|
+
// component to attach).
|
|
2662
|
+
if (route.value.component && this.routeReuseStrategy.shouldDetach(route.value.snapshot)) {
|
|
2663
|
+
this.detachAndStoreRouteSubtree(route, parentContexts);
|
|
2664
|
+
}
|
|
2665
|
+
else {
|
|
2666
|
+
this.deactivateRouteAndOutlet(route, parentContexts);
|
|
2667
|
+
}
|
|
2668
|
+
}
|
|
2669
|
+
detachAndStoreRouteSubtree(route, parentContexts) {
|
|
2670
|
+
const context = parentContexts.getContext(route.value.outlet);
|
|
2671
|
+
const contexts = context && route.value.component ? context.children : parentContexts;
|
|
2672
|
+
const children = nodeChildrenAsMap(route);
|
|
2673
|
+
for (const childOutlet of Object.keys(children)) {
|
|
2674
|
+
this.deactivateRouteAndItsChildren(children[childOutlet], contexts);
|
|
2675
|
+
}
|
|
2676
|
+
if (context && context.outlet) {
|
|
2677
|
+
const componentRef = context.outlet.detach();
|
|
2678
|
+
const contexts = context.children.onOutletDeactivated();
|
|
2679
|
+
this.routeReuseStrategy.store(route.value.snapshot, { componentRef, route, contexts });
|
|
2680
|
+
}
|
|
2681
|
+
}
|
|
2682
|
+
deactivateRouteAndOutlet(route, parentContexts) {
|
|
2683
|
+
const context = parentContexts.getContext(route.value.outlet);
|
|
2684
|
+
// The context could be `null` if we are on a componentless route but there may still be
|
|
2685
|
+
// children that need deactivating.
|
|
2686
|
+
const contexts = context && route.value.component ? context.children : parentContexts;
|
|
2687
|
+
const children = nodeChildrenAsMap(route);
|
|
2688
|
+
for (const childOutlet of Object.keys(children)) {
|
|
2689
|
+
this.deactivateRouteAndItsChildren(children[childOutlet], contexts);
|
|
2690
|
+
}
|
|
2691
|
+
if (context && context.outlet) {
|
|
2692
|
+
// Destroy the component
|
|
2693
|
+
context.outlet.deactivate();
|
|
2694
|
+
// Destroy the contexts for all the outlets that were in the component
|
|
2695
|
+
context.children.onOutletDeactivated();
|
|
2696
|
+
// Clear the information about the attached component on the context but keep the reference to
|
|
2697
|
+
// the outlet.
|
|
2698
|
+
context.attachRef = null;
|
|
2699
|
+
context.resolver = null;
|
|
2700
|
+
context.route = null;
|
|
2701
|
+
}
|
|
2702
|
+
}
|
|
2703
|
+
activateChildRoutes(futureNode, currNode, contexts) {
|
|
2704
|
+
const children = nodeChildrenAsMap(currNode);
|
|
2705
|
+
futureNode.children.forEach(c => {
|
|
2706
|
+
this.activateRoutes(c, children[c.value.outlet], contexts);
|
|
2707
|
+
this.forwardEvent(new ActivationEnd(c.value.snapshot));
|
|
2708
|
+
});
|
|
2709
|
+
if (futureNode.children.length) {
|
|
2710
|
+
this.forwardEvent(new ChildActivationEnd(futureNode.value.snapshot));
|
|
2711
|
+
}
|
|
2712
|
+
}
|
|
2713
|
+
activateRoutes(futureNode, currNode, parentContexts) {
|
|
2714
|
+
var _a;
|
|
2715
|
+
const future = futureNode.value;
|
|
2716
|
+
const curr = currNode ? currNode.value : null;
|
|
2717
|
+
advanceActivatedRoute(future);
|
|
2718
|
+
// reusing the node
|
|
2719
|
+
if (future === curr) {
|
|
2720
|
+
if (future.component) {
|
|
2721
|
+
// If we have a normal route, we need to go through an outlet.
|
|
2722
|
+
const context = parentContexts.getOrCreateContext(future.outlet);
|
|
2723
|
+
this.activateChildRoutes(futureNode, currNode, context.children);
|
|
2724
|
+
}
|
|
2725
|
+
else {
|
|
2726
|
+
// if we have a componentless route, we recurse but keep the same outlet map.
|
|
2727
|
+
this.activateChildRoutes(futureNode, currNode, parentContexts);
|
|
2728
|
+
}
|
|
2729
|
+
}
|
|
2730
|
+
else {
|
|
2731
|
+
if (future.component) {
|
|
2732
|
+
// if we have a normal route, we need to place the component into the outlet and recurse.
|
|
2733
|
+
const context = parentContexts.getOrCreateContext(future.outlet);
|
|
2734
|
+
if (this.routeReuseStrategy.shouldAttach(future.snapshot)) {
|
|
2735
|
+
const stored = this.routeReuseStrategy.retrieve(future.snapshot);
|
|
2736
|
+
this.routeReuseStrategy.store(future.snapshot, null);
|
|
2737
|
+
context.children.onOutletReAttached(stored.contexts);
|
|
2738
|
+
context.attachRef = stored.componentRef;
|
|
2739
|
+
context.route = stored.route.value;
|
|
2740
|
+
if (context.outlet) {
|
|
2741
|
+
// Attach right away when the outlet has already been instantiated
|
|
2742
|
+
// Otherwise attach from `RouterOutlet.ngOnInit` when it is instantiated
|
|
2743
|
+
context.outlet.attach(stored.componentRef, stored.route.value);
|
|
2744
|
+
}
|
|
2745
|
+
advanceActivatedRoute(stored.route.value);
|
|
2746
|
+
this.activateChildRoutes(futureNode, null, context.children);
|
|
2747
|
+
}
|
|
2748
|
+
else {
|
|
2749
|
+
const injector = getClosestRouteInjector(future.snapshot);
|
|
2750
|
+
const cmpFactoryResolver = (_a = injector === null || injector === void 0 ? void 0 : injector.get(ComponentFactoryResolver)) !== null && _a !== void 0 ? _a : null;
|
|
2751
|
+
context.attachRef = null;
|
|
2752
|
+
context.route = future;
|
|
2753
|
+
context.resolver = cmpFactoryResolver;
|
|
2754
|
+
context.injector = injector;
|
|
2755
|
+
if (context.outlet) {
|
|
2756
|
+
// Activate the outlet when it has already been instantiated
|
|
2757
|
+
// Otherwise it will get activated from its `ngOnInit` when instantiated
|
|
2758
|
+
context.outlet.activateWith(future, context.injector);
|
|
2759
|
+
}
|
|
2760
|
+
this.activateChildRoutes(futureNode, null, context.children);
|
|
2761
|
+
}
|
|
2762
|
+
}
|
|
2763
|
+
else {
|
|
2764
|
+
// if we have a componentless route, we recurse but keep the same outlet map.
|
|
2765
|
+
this.activateChildRoutes(futureNode, null, parentContexts);
|
|
2766
|
+
}
|
|
2767
|
+
}
|
|
2566
2768
|
}
|
|
2567
2769
|
}
|
|
2568
2770
|
|
|
@@ -2574,22 +2776,39 @@ class OutletInjector {
|
|
|
2574
2776
|
* found in the LICENSE file at https://angular.io/license
|
|
2575
2777
|
*/
|
|
2576
2778
|
/**
|
|
2577
|
-
*
|
|
2578
|
-
* router-outlet is needed. For example, with a config such as:
|
|
2779
|
+
* Simple function check, but generic so type inference will flow. Example:
|
|
2579
2780
|
*
|
|
2580
|
-
*
|
|
2781
|
+
* function product(a: number, b: number) {
|
|
2782
|
+
* return a * b;
|
|
2783
|
+
* }
|
|
2581
2784
|
*
|
|
2582
|
-
*
|
|
2583
|
-
*
|
|
2785
|
+
* if (isFunction<product>(fn)) {
|
|
2786
|
+
* return fn(1, 2);
|
|
2787
|
+
* } else {
|
|
2788
|
+
* throw "Must provide the `product` function";
|
|
2789
|
+
* }
|
|
2584
2790
|
*/
|
|
2585
|
-
|
|
2791
|
+
function isFunction(v) {
|
|
2792
|
+
return typeof v === 'function';
|
|
2793
|
+
}
|
|
2794
|
+
function isBoolean(v) {
|
|
2795
|
+
return typeof v === 'boolean';
|
|
2796
|
+
}
|
|
2797
|
+
function isUrlTree(v) {
|
|
2798
|
+
return v instanceof UrlTree;
|
|
2799
|
+
}
|
|
2800
|
+
function isCanLoad(guard) {
|
|
2801
|
+
return guard && isFunction(guard.canLoad);
|
|
2802
|
+
}
|
|
2803
|
+
function isCanActivate(guard) {
|
|
2804
|
+
return guard && isFunction(guard.canActivate);
|
|
2805
|
+
}
|
|
2806
|
+
function isCanActivateChild(guard) {
|
|
2807
|
+
return guard && isFunction(guard.canActivateChild);
|
|
2808
|
+
}
|
|
2809
|
+
function isCanDeactivate(guard) {
|
|
2810
|
+
return guard && isFunction(guard.canDeactivate);
|
|
2586
2811
|
}
|
|
2587
|
-
ɵEmptyOutletComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: ɵEmptyOutletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2588
|
-
ɵEmptyOutletComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "14.0.0-next.9", 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"] }] });
|
|
2589
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: ɵEmptyOutletComponent, decorators: [{
|
|
2590
|
-
type: Component,
|
|
2591
|
-
args: [{ template: `<router-outlet></router-outlet>` }]
|
|
2592
|
-
}] });
|
|
2593
2812
|
|
|
2594
2813
|
/**
|
|
2595
2814
|
* @license
|
|
@@ -2598,113 +2817,36 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9",
|
|
|
2598
2817
|
* Use of this source code is governed by an MIT-style license that can be
|
|
2599
2818
|
* found in the LICENSE file at https://angular.io/license
|
|
2600
2819
|
*/
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
if (route.redirectTo && route.children) {
|
|
2632
|
-
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and children cannot be used together`);
|
|
2633
|
-
}
|
|
2634
|
-
if (route.redirectTo && route.loadChildren) {
|
|
2635
|
-
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and loadChildren cannot be used together`);
|
|
2636
|
-
}
|
|
2637
|
-
if (route.children && route.loadChildren) {
|
|
2638
|
-
throw new Error(`Invalid configuration of route '${fullPath}': children and loadChildren cannot be used together`);
|
|
2639
|
-
}
|
|
2640
|
-
if (route.redirectTo && route.component) {
|
|
2641
|
-
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and component cannot be used together`);
|
|
2642
|
-
}
|
|
2643
|
-
if (route.redirectTo && route.canActivate) {
|
|
2644
|
-
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and canActivate cannot be used together. Redirects happen before activation ` +
|
|
2645
|
-
`so canActivate will never be executed.`);
|
|
2646
|
-
}
|
|
2647
|
-
if (route.path && route.matcher) {
|
|
2648
|
-
throw new Error(`Invalid configuration of route '${fullPath}': path and matcher cannot be used together`);
|
|
2649
|
-
}
|
|
2650
|
-
if (route.redirectTo === void 0 && !route.component && !route.children && !route.loadChildren) {
|
|
2651
|
-
throw new Error(`Invalid configuration of route '${fullPath}'. One of the following must be provided: component, redirectTo, children or loadChildren`);
|
|
2652
|
-
}
|
|
2653
|
-
if (route.path === void 0 && route.matcher === void 0) {
|
|
2654
|
-
throw new Error(`Invalid configuration of route '${fullPath}': routes must have either a path or a matcher specified`);
|
|
2655
|
-
}
|
|
2656
|
-
if (typeof route.path === 'string' && route.path.charAt(0) === '/') {
|
|
2657
|
-
throw new Error(`Invalid configuration of route '${fullPath}': path cannot start with a slash`);
|
|
2658
|
-
}
|
|
2659
|
-
if (route.path === '' && route.redirectTo !== void 0 && route.pathMatch === void 0) {
|
|
2660
|
-
const exp = `The default value of 'pathMatch' is 'prefix', but often the intent is to use 'full'.`;
|
|
2661
|
-
throw new Error(`Invalid configuration of route '{path: "${fullPath}", redirectTo: "${route.redirectTo}"}': please provide 'pathMatch'. ${exp}`);
|
|
2662
|
-
}
|
|
2663
|
-
}
|
|
2664
|
-
if (route.children) {
|
|
2665
|
-
validateConfig(route.children, fullPath);
|
|
2666
|
-
}
|
|
2667
|
-
}
|
|
2668
|
-
function getFullPath(parentPath, currentRoute) {
|
|
2669
|
-
if (!currentRoute) {
|
|
2670
|
-
return parentPath;
|
|
2671
|
-
}
|
|
2672
|
-
if (!parentPath && !currentRoute.path) {
|
|
2673
|
-
return '';
|
|
2674
|
-
}
|
|
2675
|
-
else if (parentPath && !currentRoute.path) {
|
|
2676
|
-
return `${parentPath}/`;
|
|
2677
|
-
}
|
|
2678
|
-
else if (!parentPath && currentRoute.path) {
|
|
2679
|
-
return currentRoute.path;
|
|
2680
|
-
}
|
|
2681
|
-
else {
|
|
2682
|
-
return `${parentPath}/${currentRoute.path}`;
|
|
2683
|
-
}
|
|
2684
|
-
}
|
|
2685
|
-
/**
|
|
2686
|
-
* Makes a copy of the config and adds any default required properties.
|
|
2687
|
-
*/
|
|
2688
|
-
function standardizeConfig(r) {
|
|
2689
|
-
const children = r.children && r.children.map(standardizeConfig);
|
|
2690
|
-
const c = children ? Object.assign(Object.assign({}, r), { children }) : Object.assign({}, r);
|
|
2691
|
-
if (!c.component && (children || c.loadChildren) && (c.outlet && c.outlet !== PRIMARY_OUTLET)) {
|
|
2692
|
-
c.component = ɵEmptyOutletComponent;
|
|
2693
|
-
}
|
|
2694
|
-
return c;
|
|
2695
|
-
}
|
|
2696
|
-
/** Returns the `route.outlet` or PRIMARY_OUTLET if none exists. */
|
|
2697
|
-
function getOutlet(route) {
|
|
2698
|
-
return route.outlet || PRIMARY_OUTLET;
|
|
2699
|
-
}
|
|
2700
|
-
/**
|
|
2701
|
-
* Sorts the `routes` such that the ones with an outlet matching `outletName` come first.
|
|
2702
|
-
* The order of the configs is otherwise preserved.
|
|
2703
|
-
*/
|
|
2704
|
-
function sortByMatchingOutlets(routes, outletName) {
|
|
2705
|
-
const sortedConfig = routes.filter(r => getOutlet(r) === outletName);
|
|
2706
|
-
sortedConfig.push(...routes.filter(r => getOutlet(r) !== outletName));
|
|
2707
|
-
return sortedConfig;
|
|
2820
|
+
const INITIAL_VALUE = Symbol('INITIAL_VALUE');
|
|
2821
|
+
function prioritizedGuardValue() {
|
|
2822
|
+
return switchMap(obs => {
|
|
2823
|
+
return combineLatest(obs.map(o => o.pipe(take(1), startWith(INITIAL_VALUE))))
|
|
2824
|
+
.pipe(scan((acc, list) => {
|
|
2825
|
+
let isPending = false;
|
|
2826
|
+
return list.reduce((innerAcc, val, i) => {
|
|
2827
|
+
if (innerAcc !== INITIAL_VALUE)
|
|
2828
|
+
return innerAcc;
|
|
2829
|
+
// Toggle pending flag if any values haven't been set yet
|
|
2830
|
+
if (val === INITIAL_VALUE)
|
|
2831
|
+
isPending = true;
|
|
2832
|
+
// Any other return values are only valid if we haven't yet hit a pending
|
|
2833
|
+
// call. This guarantees that in the case of a guard at the bottom of the
|
|
2834
|
+
// tree that returns a redirect, we will wait for the higher priority
|
|
2835
|
+
// guard at the top to finish before performing the redirect.
|
|
2836
|
+
if (!isPending) {
|
|
2837
|
+
// Early return when we hit a `false` value as that should always
|
|
2838
|
+
// cancel navigation
|
|
2839
|
+
if (val === false)
|
|
2840
|
+
return val;
|
|
2841
|
+
if (i === list.length - 1 || isUrlTree(val)) {
|
|
2842
|
+
return val;
|
|
2843
|
+
}
|
|
2844
|
+
}
|
|
2845
|
+
return innerAcc;
|
|
2846
|
+
}, acc);
|
|
2847
|
+
}, INITIAL_VALUE), filter(item => item !== INITIAL_VALUE), map(item => isUrlTree(item) ? item : item === true), //
|
|
2848
|
+
take(1));
|
|
2849
|
+
});
|
|
2708
2850
|
}
|
|
2709
2851
|
|
|
2710
2852
|
/**
|
|
@@ -2782,6 +2924,9 @@ function addEmptyPathsToChildrenIfNeeded(segmentGroup, consumedSegments, slicedS
|
|
|
2782
2924
|
s._sourceSegment = segmentGroup;
|
|
2783
2925
|
if (relativeLinkResolution === 'legacy') {
|
|
2784
2926
|
s._segmentIndexShift = segmentGroup.segments.length;
|
|
2927
|
+
if (typeof ngDevMode === 'undefined' || !!ngDevMode) {
|
|
2928
|
+
s._segmentIndexShiftCorrected = consumedSegments.length;
|
|
2929
|
+
}
|
|
2785
2930
|
}
|
|
2786
2931
|
else {
|
|
2787
2932
|
s._segmentIndexShift = consumedSegments.length;
|
|
@@ -2882,17 +3027,17 @@ function canLoadFails(route) {
|
|
|
2882
3027
|
*
|
|
2883
3028
|
* Lazy modules are loaded along the way.
|
|
2884
3029
|
*/
|
|
2885
|
-
function applyRedirects$1(
|
|
2886
|
-
return new ApplyRedirects(
|
|
3030
|
+
function applyRedirects$1(injector, configLoader, urlSerializer, urlTree, config) {
|
|
3031
|
+
return new ApplyRedirects(injector, configLoader, urlSerializer, urlTree, config).apply();
|
|
2887
3032
|
}
|
|
2888
3033
|
class ApplyRedirects {
|
|
2889
|
-
constructor(
|
|
3034
|
+
constructor(injector, configLoader, urlSerializer, urlTree, config) {
|
|
3035
|
+
this.injector = injector;
|
|
2890
3036
|
this.configLoader = configLoader;
|
|
2891
3037
|
this.urlSerializer = urlSerializer;
|
|
2892
3038
|
this.urlTree = urlTree;
|
|
2893
3039
|
this.config = config;
|
|
2894
3040
|
this.allowRedirects = true;
|
|
2895
|
-
this.ngModule = moduleInjector.get(NgModuleRef);
|
|
2896
3041
|
}
|
|
2897
3042
|
apply() {
|
|
2898
3043
|
const splitGroup = split(this.urlTree.root, [], [], this.config).segmentGroup;
|
|
@@ -2903,7 +3048,7 @@ class ApplyRedirects {
|
|
|
2903
3048
|
// them. We should be able to remove this logic as a "breaking change" but should do some more
|
|
2904
3049
|
// investigation into the failures first.
|
|
2905
3050
|
const rootSegmentGroup = new UrlSegmentGroup(splitGroup.segments, splitGroup.children);
|
|
2906
|
-
const expanded$ = this.expandSegmentGroup(this.
|
|
3051
|
+
const expanded$ = this.expandSegmentGroup(this.injector, this.config, rootSegmentGroup, PRIMARY_OUTLET);
|
|
2907
3052
|
const urlTrees$ = expanded$.pipe(map((rootSegmentGroup) => {
|
|
2908
3053
|
return this.createUrlTree(squashSegmentGroup(rootSegmentGroup), this.urlTree.queryParams, this.urlTree.fragment);
|
|
2909
3054
|
}));
|
|
@@ -2922,7 +3067,7 @@ class ApplyRedirects {
|
|
|
2922
3067
|
}));
|
|
2923
3068
|
}
|
|
2924
3069
|
match(tree) {
|
|
2925
|
-
const expanded$ = this.expandSegmentGroup(this.
|
|
3070
|
+
const expanded$ = this.expandSegmentGroup(this.injector, this.config, tree.root, PRIMARY_OUTLET);
|
|
2926
3071
|
const mapped$ = expanded$.pipe(map((rootSegmentGroup) => {
|
|
2927
3072
|
return this.createUrlTree(squashSegmentGroup(rootSegmentGroup), tree.queryParams, tree.fragment);
|
|
2928
3073
|
}));
|
|
@@ -2942,15 +3087,15 @@ class ApplyRedirects {
|
|
|
2942
3087
|
rootCandidate;
|
|
2943
3088
|
return new UrlTree(root, queryParams, fragment);
|
|
2944
3089
|
}
|
|
2945
|
-
expandSegmentGroup(
|
|
3090
|
+
expandSegmentGroup(injector, routes, segmentGroup, outlet) {
|
|
2946
3091
|
if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) {
|
|
2947
|
-
return this.expandChildren(
|
|
3092
|
+
return this.expandChildren(injector, routes, segmentGroup)
|
|
2948
3093
|
.pipe(map((children) => new UrlSegmentGroup([], children)));
|
|
2949
3094
|
}
|
|
2950
|
-
return this.expandSegment(
|
|
3095
|
+
return this.expandSegment(injector, segmentGroup, routes, segmentGroup.segments, outlet, true);
|
|
2951
3096
|
}
|
|
2952
3097
|
// Recursively expand segment groups for all the child outlets
|
|
2953
|
-
expandChildren(
|
|
3098
|
+
expandChildren(injector, routes, segmentGroup) {
|
|
2954
3099
|
// Expand outlets one at a time, starting with the primary outlet. We need to do it this way
|
|
2955
3100
|
// because an absolute redirect from the primary outlet takes precedence.
|
|
2956
3101
|
const childOutlets = [];
|
|
@@ -2969,16 +3114,16 @@ class ApplyRedirects {
|
|
|
2969
3114
|
// first, followed by routes for other outlets, which might match if they have an
|
|
2970
3115
|
// empty path.
|
|
2971
3116
|
const sortedRoutes = sortByMatchingOutlets(routes, childOutlet);
|
|
2972
|
-
return this.expandSegmentGroup(
|
|
3117
|
+
return this.expandSegmentGroup(injector, sortedRoutes, child, childOutlet)
|
|
2973
3118
|
.pipe(map(s => ({ segment: s, outlet: childOutlet })));
|
|
2974
3119
|
}), scan((children, expandedChild) => {
|
|
2975
3120
|
children[expandedChild.outlet] = expandedChild.segment;
|
|
2976
3121
|
return children;
|
|
2977
3122
|
}, {}), last$1());
|
|
2978
3123
|
}
|
|
2979
|
-
expandSegment(
|
|
2980
|
-
return from(routes).pipe(concatMap(
|
|
2981
|
-
const expanded$ = this.expandSegmentAgainstRoute(
|
|
3124
|
+
expandSegment(injector, segmentGroup, routes, segments, outlet, allowRedirects) {
|
|
3125
|
+
return from(routes).pipe(concatMap(r => {
|
|
3126
|
+
const expanded$ = this.expandSegmentAgainstRoute(injector, segmentGroup, routes, r, segments, outlet, allowRedirects);
|
|
2982
3127
|
return expanded$.pipe(catchError((e) => {
|
|
2983
3128
|
if (e instanceof NoMatch$1) {
|
|
2984
3129
|
return of(null);
|
|
@@ -2995,35 +3140,35 @@ class ApplyRedirects {
|
|
|
2995
3140
|
throw e;
|
|
2996
3141
|
}));
|
|
2997
3142
|
}
|
|
2998
|
-
expandSegmentAgainstRoute(
|
|
3143
|
+
expandSegmentAgainstRoute(injector, segmentGroup, routes, route, paths, outlet, allowRedirects) {
|
|
2999
3144
|
if (!isImmediateMatch(route, segmentGroup, paths, outlet)) {
|
|
3000
3145
|
return noMatch(segmentGroup);
|
|
3001
3146
|
}
|
|
3002
3147
|
if (route.redirectTo === undefined) {
|
|
3003
|
-
return this.matchSegmentAgainstRoute(
|
|
3148
|
+
return this.matchSegmentAgainstRoute(injector, segmentGroup, route, paths, outlet);
|
|
3004
3149
|
}
|
|
3005
3150
|
if (allowRedirects && this.allowRedirects) {
|
|
3006
|
-
return this.expandSegmentAgainstRouteUsingRedirect(
|
|
3151
|
+
return this.expandSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, paths, outlet);
|
|
3007
3152
|
}
|
|
3008
3153
|
return noMatch(segmentGroup);
|
|
3009
3154
|
}
|
|
3010
|
-
expandSegmentAgainstRouteUsingRedirect(
|
|
3155
|
+
expandSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet) {
|
|
3011
3156
|
if (route.path === '**') {
|
|
3012
|
-
return this.expandWildCardWithParamsAgainstRouteUsingRedirect(
|
|
3157
|
+
return this.expandWildCardWithParamsAgainstRouteUsingRedirect(injector, routes, route, outlet);
|
|
3013
3158
|
}
|
|
3014
|
-
return this.expandRegularSegmentAgainstRouteUsingRedirect(
|
|
3159
|
+
return this.expandRegularSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet);
|
|
3015
3160
|
}
|
|
3016
|
-
expandWildCardWithParamsAgainstRouteUsingRedirect(
|
|
3161
|
+
expandWildCardWithParamsAgainstRouteUsingRedirect(injector, routes, route, outlet) {
|
|
3017
3162
|
const newTree = this.applyRedirectCommands([], route.redirectTo, {});
|
|
3018
3163
|
if (route.redirectTo.startsWith('/')) {
|
|
3019
3164
|
return absoluteRedirect(newTree);
|
|
3020
3165
|
}
|
|
3021
3166
|
return this.lineralizeSegments(route, newTree).pipe(mergeMap((newSegments) => {
|
|
3022
3167
|
const group = new UrlSegmentGroup(newSegments, {});
|
|
3023
|
-
return this.expandSegment(
|
|
3168
|
+
return this.expandSegment(injector, group, routes, newSegments, outlet, false);
|
|
3024
3169
|
}));
|
|
3025
3170
|
}
|
|
3026
|
-
expandRegularSegmentAgainstRouteUsingRedirect(
|
|
3171
|
+
expandRegularSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet) {
|
|
3027
3172
|
const { matched, consumedSegments, remainingSegments, positionalParamSegments } = match(segmentGroup, route, segments);
|
|
3028
3173
|
if (!matched)
|
|
3029
3174
|
return noMatch(segmentGroup);
|
|
@@ -3032,16 +3177,20 @@ class ApplyRedirects {
|
|
|
3032
3177
|
return absoluteRedirect(newTree);
|
|
3033
3178
|
}
|
|
3034
3179
|
return this.lineralizeSegments(route, newTree).pipe(mergeMap((newSegments) => {
|
|
3035
|
-
return this.expandSegment(
|
|
3180
|
+
return this.expandSegment(injector, segmentGroup, routes, newSegments.concat(remainingSegments), outlet, false);
|
|
3036
3181
|
}));
|
|
3037
3182
|
}
|
|
3038
|
-
matchSegmentAgainstRoute(
|
|
3183
|
+
matchSegmentAgainstRoute(injector, rawSegmentGroup, route, segments, outlet) {
|
|
3039
3184
|
if (route.path === '**') {
|
|
3185
|
+
// Only create the Route's `EnvironmentInjector` if it matches the attempted navigation
|
|
3186
|
+
injector = getOrCreateRouteInjectorIfNeeded(route, injector);
|
|
3040
3187
|
if (route.loadChildren) {
|
|
3041
|
-
const loaded$ = route.
|
|
3042
|
-
|
|
3188
|
+
const loaded$ = route._loadedRoutes ?
|
|
3189
|
+
of({ routes: route._loadedRoutes, injector: route._loadedInjector }) :
|
|
3190
|
+
this.configLoader.loadChildren(injector, route);
|
|
3043
3191
|
return loaded$.pipe(map((cfg) => {
|
|
3044
|
-
route.
|
|
3192
|
+
route._loadedRoutes = cfg.routes;
|
|
3193
|
+
route._loadedInjector = cfg.injector;
|
|
3045
3194
|
return new UrlSegmentGroup(segments, {});
|
|
3046
3195
|
}));
|
|
3047
3196
|
}
|
|
@@ -3050,55 +3199,58 @@ class ApplyRedirects {
|
|
|
3050
3199
|
const { matched, consumedSegments, remainingSegments } = match(rawSegmentGroup, route, segments);
|
|
3051
3200
|
if (!matched)
|
|
3052
3201
|
return noMatch(rawSegmentGroup);
|
|
3053
|
-
|
|
3202
|
+
// Only create the Route's `EnvironmentInjector` if it matches the attempted navigation
|
|
3203
|
+
injector = getOrCreateRouteInjectorIfNeeded(route, injector);
|
|
3204
|
+
const childConfig$ = this.getChildConfig(injector, route, segments);
|
|
3054
3205
|
return childConfig$.pipe(mergeMap((routerConfig) => {
|
|
3055
|
-
|
|
3206
|
+
var _a;
|
|
3207
|
+
const childInjector = (_a = routerConfig.injector) !== null && _a !== void 0 ? _a : injector;
|
|
3056
3208
|
const childConfig = routerConfig.routes;
|
|
3057
3209
|
const { segmentGroup: splitSegmentGroup, slicedSegments } = split(rawSegmentGroup, consumedSegments, remainingSegments, childConfig);
|
|
3058
3210
|
// See comment on the other call to `split` about why this is necessary.
|
|
3059
3211
|
const segmentGroup = new UrlSegmentGroup(splitSegmentGroup.segments, splitSegmentGroup.children);
|
|
3060
3212
|
if (slicedSegments.length === 0 && segmentGroup.hasChildren()) {
|
|
3061
|
-
const expanded$ = this.expandChildren(
|
|
3213
|
+
const expanded$ = this.expandChildren(childInjector, childConfig, segmentGroup);
|
|
3062
3214
|
return expanded$.pipe(map((children) => new UrlSegmentGroup(consumedSegments, children)));
|
|
3063
3215
|
}
|
|
3064
3216
|
if (childConfig.length === 0 && slicedSegments.length === 0) {
|
|
3065
3217
|
return of(new UrlSegmentGroup(consumedSegments, {}));
|
|
3066
3218
|
}
|
|
3067
3219
|
const matchedOnOutlet = getOutlet(route) === outlet;
|
|
3068
|
-
const expanded$ = this.expandSegment(
|
|
3220
|
+
const expanded$ = this.expandSegment(childInjector, segmentGroup, childConfig, slicedSegments, matchedOnOutlet ? PRIMARY_OUTLET : outlet, true);
|
|
3069
3221
|
return expanded$.pipe(map((cs) => new UrlSegmentGroup(consumedSegments.concat(cs.segments), cs.children)));
|
|
3070
3222
|
}));
|
|
3071
3223
|
}
|
|
3072
|
-
getChildConfig(
|
|
3224
|
+
getChildConfig(injector, route, segments) {
|
|
3073
3225
|
if (route.children) {
|
|
3074
3226
|
// The children belong to the same module
|
|
3075
|
-
return of(
|
|
3227
|
+
return of({ routes: route.children, injector });
|
|
3076
3228
|
}
|
|
3077
3229
|
if (route.loadChildren) {
|
|
3078
3230
|
// lazy children belong to the loaded module
|
|
3079
|
-
if (route.
|
|
3080
|
-
return of(route.
|
|
3231
|
+
if (route._loadedRoutes !== undefined) {
|
|
3232
|
+
return of({ routes: route._loadedRoutes, injector: route._loadedInjector });
|
|
3081
3233
|
}
|
|
3082
|
-
return this.runCanLoadGuards(
|
|
3234
|
+
return this.runCanLoadGuards(injector, route, segments)
|
|
3083
3235
|
.pipe(mergeMap((shouldLoadResult) => {
|
|
3084
3236
|
if (shouldLoadResult) {
|
|
3085
|
-
return this.configLoader.
|
|
3086
|
-
.pipe(
|
|
3087
|
-
route.
|
|
3088
|
-
|
|
3237
|
+
return this.configLoader.loadChildren(injector, route)
|
|
3238
|
+
.pipe(tap((cfg) => {
|
|
3239
|
+
route._loadedRoutes = cfg.routes;
|
|
3240
|
+
route._loadedInjector = cfg.injector;
|
|
3089
3241
|
}));
|
|
3090
3242
|
}
|
|
3091
3243
|
return canLoadFails(route);
|
|
3092
3244
|
}));
|
|
3093
3245
|
}
|
|
3094
|
-
return of(
|
|
3246
|
+
return of({ routes: [], injector });
|
|
3095
3247
|
}
|
|
3096
|
-
runCanLoadGuards(
|
|
3248
|
+
runCanLoadGuards(injector, route, segments) {
|
|
3097
3249
|
const canLoad = route.canLoad;
|
|
3098
3250
|
if (!canLoad || canLoad.length === 0)
|
|
3099
3251
|
return of(true);
|
|
3100
3252
|
const canLoadObservables = canLoad.map((injectionToken) => {
|
|
3101
|
-
const guard =
|
|
3253
|
+
const guard = injector.get(injectionToken);
|
|
3102
3254
|
let guardVal;
|
|
3103
3255
|
if (isCanLoad(guard)) {
|
|
3104
3256
|
guardVal = guard.canLoad(route, segments);
|
|
@@ -3226,8 +3378,8 @@ function squashSegmentGroup(segmentGroup) {
|
|
|
3226
3378
|
* Use of this source code is governed by an MIT-style license that can be
|
|
3227
3379
|
* found in the LICENSE file at https://angular.io/license
|
|
3228
3380
|
*/
|
|
3229
|
-
function applyRedirects(
|
|
3230
|
-
return switchMap(t => applyRedirects$1(
|
|
3381
|
+
function applyRedirects(environmentInjector, configLoader, urlSerializer, config) {
|
|
3382
|
+
return switchMap(t => applyRedirects$1(environmentInjector, configLoader, urlSerializer, t.extractedUrl, config)
|
|
3231
3383
|
.pipe(map(urlAfterRedirects => (Object.assign(Object.assign({}, t), { urlAfterRedirects })))));
|
|
3232
3384
|
}
|
|
3233
3385
|
|
|
@@ -3261,21 +3413,11 @@ function getCanActivateChild(p) {
|
|
|
3261
3413
|
return null;
|
|
3262
3414
|
return { node: p, guards: canActivateChild };
|
|
3263
3415
|
}
|
|
3264
|
-
function getToken(token, snapshot,
|
|
3265
|
-
const
|
|
3266
|
-
const injector =
|
|
3416
|
+
function getToken(token, snapshot, fallbackInjector) {
|
|
3417
|
+
const routeInjector = getClosestRouteInjector(snapshot);
|
|
3418
|
+
const injector = routeInjector !== null && routeInjector !== void 0 ? routeInjector : fallbackInjector;
|
|
3267
3419
|
return injector.get(token);
|
|
3268
3420
|
}
|
|
3269
|
-
function getClosestLoadedConfig(snapshot) {
|
|
3270
|
-
if (!snapshot)
|
|
3271
|
-
return null;
|
|
3272
|
-
for (let s = snapshot.parent; s; s = s.parent) {
|
|
3273
|
-
const route = s.routeConfig;
|
|
3274
|
-
if (route && route._loadedConfig)
|
|
3275
|
-
return route._loadedConfig;
|
|
3276
|
-
}
|
|
3277
|
-
return null;
|
|
3278
|
-
}
|
|
3279
3421
|
function getChildRouteGuards(futureNode, currNode, contexts, futurePath, checks = {
|
|
3280
3422
|
canDeactivateChecks: [],
|
|
3281
3423
|
canActivateChecks: []
|
|
@@ -3519,6 +3661,7 @@ function runCanDeactivate(component, currARS, currRSS, futureRSS, moduleInjector
|
|
|
3519
3661
|
* Use of this source code is governed by an MIT-style license that can be
|
|
3520
3662
|
* found in the LICENSE file at https://angular.io/license
|
|
3521
3663
|
*/
|
|
3664
|
+
const NG_DEV_MODE$2 = typeof ngDevMode === 'undefined' || !!ngDevMode;
|
|
3522
3665
|
class NoMatch {
|
|
3523
3666
|
}
|
|
3524
3667
|
function newObservableError(e) {
|
|
@@ -3627,6 +3770,7 @@ class Recognizer {
|
|
|
3627
3770
|
return null;
|
|
3628
3771
|
}
|
|
3629
3772
|
processSegmentAgainstRoute(route, rawSegment, segments, outlet) {
|
|
3773
|
+
var _a, _b, _c, _d;
|
|
3630
3774
|
if (route.redirectTo || !isImmediateMatch(route, rawSegment, segments, outlet))
|
|
3631
3775
|
return null;
|
|
3632
3776
|
let snapshot;
|
|
@@ -3634,7 +3778,13 @@ class Recognizer {
|
|
|
3634
3778
|
let remainingSegments = [];
|
|
3635
3779
|
if (route.path === '**') {
|
|
3636
3780
|
const params = segments.length > 0 ? last(segments).parameters : {};
|
|
3637
|
-
|
|
3781
|
+
const pathIndexShift = getPathIndexShift(rawSegment) + segments.length;
|
|
3782
|
+
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),
|
|
3783
|
+
// NG_DEV_MODE is used to prevent the getCorrectedPathIndexShift function from affecting
|
|
3784
|
+
// production bundle size. This value is intended only to surface a warning to users
|
|
3785
|
+
// depending on `relativeLinkResolution: 'legacy'` in dev mode.
|
|
3786
|
+
(NG_DEV_MODE$2 ? getCorrectedPathIndexShift(rawSegment) + segments.length :
|
|
3787
|
+
pathIndexShift));
|
|
3638
3788
|
}
|
|
3639
3789
|
else {
|
|
3640
3790
|
const result = match(rawSegment, route, segments);
|
|
@@ -3643,7 +3793,9 @@ class Recognizer {
|
|
|
3643
3793
|
}
|
|
3644
3794
|
consumedSegments = result.consumedSegments;
|
|
3645
3795
|
remainingSegments = result.remainingSegments;
|
|
3646
|
-
|
|
3796
|
+
const pathIndexShift = getPathIndexShift(rawSegment) + consumedSegments.length;
|
|
3797
|
+
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 :
|
|
3798
|
+
pathIndexShift));
|
|
3647
3799
|
}
|
|
3648
3800
|
const childConfig = getChildConfig(route);
|
|
3649
3801
|
const { segmentGroup, slicedSegments } = split(rawSegment, consumedSegments, remainingSegments,
|
|
@@ -3691,7 +3843,7 @@ function getChildConfig(route) {
|
|
|
3691
3843
|
return route.children;
|
|
3692
3844
|
}
|
|
3693
3845
|
if (route.loadChildren) {
|
|
3694
|
-
return route.
|
|
3846
|
+
return route._loadedRoutes;
|
|
3695
3847
|
}
|
|
3696
3848
|
return [];
|
|
3697
3849
|
}
|
|
@@ -3752,11 +3904,22 @@ function getSourceSegmentGroup(segmentGroup) {
|
|
|
3752
3904
|
return s;
|
|
3753
3905
|
}
|
|
3754
3906
|
function getPathIndexShift(segmentGroup) {
|
|
3907
|
+
var _a, _b;
|
|
3908
|
+
let s = segmentGroup;
|
|
3909
|
+
let res = (_a = s._segmentIndexShift) !== null && _a !== void 0 ? _a : 0;
|
|
3910
|
+
while (s._sourceSegment) {
|
|
3911
|
+
s = s._sourceSegment;
|
|
3912
|
+
res += (_b = s._segmentIndexShift) !== null && _b !== void 0 ? _b : 0;
|
|
3913
|
+
}
|
|
3914
|
+
return res - 1;
|
|
3915
|
+
}
|
|
3916
|
+
function getCorrectedPathIndexShift(segmentGroup) {
|
|
3917
|
+
var _a, _b, _c, _d;
|
|
3755
3918
|
let s = segmentGroup;
|
|
3756
|
-
let res = (s.
|
|
3919
|
+
let res = (_b = (_a = s._segmentIndexShiftCorrected) !== null && _a !== void 0 ? _a : s._segmentIndexShift) !== null && _b !== void 0 ? _b : 0;
|
|
3757
3920
|
while (s._sourceSegment) {
|
|
3758
3921
|
s = s._sourceSegment;
|
|
3759
|
-
res += (s.
|
|
3922
|
+
res += (_d = (_c = s._segmentIndexShiftCorrected) !== null && _c !== void 0 ? _c : s._segmentIndexShift) !== null && _d !== void 0 ? _d : 0;
|
|
3760
3923
|
}
|
|
3761
3924
|
return res - 1;
|
|
3762
3925
|
}
|
|
@@ -3806,19 +3969,16 @@ function resolveData(paramsInheritanceStrategy, moduleInjector) {
|
|
|
3806
3969
|
function runResolve(futureARS, futureRSS, paramsInheritanceStrategy, moduleInjector) {
|
|
3807
3970
|
const config = futureARS.routeConfig;
|
|
3808
3971
|
const resolve = futureARS._resolve;
|
|
3809
|
-
|
|
3810
|
-
|
|
3811
|
-
if (typeof config.title === 'string' || config.title === null) {
|
|
3812
|
-
data[RouteTitle] = config.title;
|
|
3813
|
-
}
|
|
3814
|
-
else {
|
|
3815
|
-
resolve[RouteTitle] = config.title;
|
|
3816
|
-
}
|
|
3972
|
+
if ((config === null || config === void 0 ? void 0 : config.title) !== undefined && !hasStaticTitle(config)) {
|
|
3973
|
+
resolve[RouteTitle] = config.title;
|
|
3817
3974
|
}
|
|
3818
3975
|
return resolveNode(resolve, futureARS, futureRSS, moduleInjector)
|
|
3819
3976
|
.pipe(map((resolvedData) => {
|
|
3820
3977
|
futureARS._resolvedData = resolvedData;
|
|
3821
|
-
futureARS.data =
|
|
3978
|
+
futureARS.data = inheritedParamsDataResolve(futureARS, paramsInheritanceStrategy).resolve;
|
|
3979
|
+
if (config && hasStaticTitle(config)) {
|
|
3980
|
+
futureARS.data[RouteTitle] = config.title;
|
|
3981
|
+
}
|
|
3822
3982
|
return null;
|
|
3823
3983
|
}));
|
|
3824
3984
|
}
|
|
@@ -3829,16 +3989,9 @@ function resolveNode(resolve, futureARS, futureRSS, moduleInjector) {
|
|
|
3829
3989
|
}
|
|
3830
3990
|
const data = {};
|
|
3831
3991
|
return from(keys).pipe(mergeMap(key => getResolver(resolve[key], futureARS, futureRSS, moduleInjector)
|
|
3832
|
-
.pipe(
|
|
3992
|
+
.pipe(first(), tap((value) => {
|
|
3833
3993
|
data[key] = value;
|
|
3834
|
-
}))), takeLast(1),
|
|
3835
|
-
// Ensure all resolvers returned values, otherwise don't emit any "next" and just complete
|
|
3836
|
-
// the chain which will cancel navigation
|
|
3837
|
-
if (getDataKeys(data).length === keys.length) {
|
|
3838
|
-
return of(data);
|
|
3839
|
-
}
|
|
3840
|
-
return EMPTY;
|
|
3841
|
-
}));
|
|
3994
|
+
}))), takeLast(1), mapTo(data), catchError((e) => e instanceof EmptyError ? EMPTY : throwError(e)));
|
|
3842
3995
|
}
|
|
3843
3996
|
function getDataKeys(obj) {
|
|
3844
3997
|
return [...Object.keys(obj), ...Object.getOwnPropertySymbols(obj)];
|
|
@@ -3848,6 +4001,9 @@ function getResolver(injectionToken, futureARS, futureRSS, moduleInjector) {
|
|
|
3848
4001
|
return resolver.resolve ? wrapIntoObservable(resolver.resolve(futureARS, futureRSS)) :
|
|
3849
4002
|
wrapIntoObservable(resolver(futureARS, futureRSS));
|
|
3850
4003
|
}
|
|
4004
|
+
function hasStaticTitle(config) {
|
|
4005
|
+
return typeof config.title === 'string' || config.title === null;
|
|
4006
|
+
}
|
|
3851
4007
|
|
|
3852
4008
|
/**
|
|
3853
4009
|
* @license
|
|
@@ -3944,6 +4100,7 @@ class DefaultRouteReuseStrategy extends BaseRouteReuseStrategy {
|
|
|
3944
4100
|
* Use of this source code is governed by an MIT-style license that can be
|
|
3945
4101
|
* found in the LICENSE file at https://angular.io/license
|
|
3946
4102
|
*/
|
|
4103
|
+
const NG_DEV_MODE$1 = typeof ngDevMode === 'undefined' || !!ngDevMode;
|
|
3947
4104
|
/**
|
|
3948
4105
|
* The [DI token](guide/glossary/#di-token) for a router configuration.
|
|
3949
4106
|
*
|
|
@@ -3956,43 +4113,85 @@ class DefaultRouteReuseStrategy extends BaseRouteReuseStrategy {
|
|
|
3956
4113
|
*/
|
|
3957
4114
|
const ROUTES = new InjectionToken('ROUTES');
|
|
3958
4115
|
class RouterConfigLoader {
|
|
3959
|
-
constructor(injector, compiler
|
|
4116
|
+
constructor(injector, compiler) {
|
|
3960
4117
|
this.injector = injector;
|
|
3961
4118
|
this.compiler = compiler;
|
|
3962
|
-
this.
|
|
3963
|
-
this.
|
|
4119
|
+
this.componentLoaders = new WeakMap();
|
|
4120
|
+
this.childrenLoaders = new WeakMap();
|
|
4121
|
+
}
|
|
4122
|
+
loadComponent(route) {
|
|
4123
|
+
if (this.componentLoaders.get(route)) {
|
|
4124
|
+
return this.componentLoaders.get(route);
|
|
4125
|
+
}
|
|
4126
|
+
else if (route._loadedComponent) {
|
|
4127
|
+
return of(route._loadedComponent);
|
|
4128
|
+
}
|
|
4129
|
+
if (this.onLoadStartListener) {
|
|
4130
|
+
this.onLoadStartListener(route);
|
|
4131
|
+
}
|
|
4132
|
+
const loadRunner = wrapIntoObservable(route.loadComponent())
|
|
4133
|
+
.pipe(tap(component => {
|
|
4134
|
+
var _a;
|
|
4135
|
+
if (this.onLoadEndListener) {
|
|
4136
|
+
this.onLoadEndListener(route);
|
|
4137
|
+
}
|
|
4138
|
+
NG_DEV_MODE$1 && assertStandalone((_a = route.path) !== null && _a !== void 0 ? _a : '', component);
|
|
4139
|
+
route._loadedComponent = component;
|
|
4140
|
+
}), finalize(() => {
|
|
4141
|
+
this.componentLoaders.delete(route);
|
|
4142
|
+
}));
|
|
4143
|
+
// Use custom ConnectableObservable as share in runners pipe increasing the bundle size too much
|
|
4144
|
+
const loader = new ConnectableObservable(loadRunner, () => new Subject()).pipe(refCount());
|
|
4145
|
+
this.componentLoaders.set(route, loader);
|
|
4146
|
+
return loader;
|
|
3964
4147
|
}
|
|
3965
|
-
|
|
3966
|
-
if (route
|
|
3967
|
-
return route
|
|
4148
|
+
loadChildren(parentInjector, route) {
|
|
4149
|
+
if (this.childrenLoaders.get(route)) {
|
|
4150
|
+
return this.childrenLoaders.get(route);
|
|
4151
|
+
}
|
|
4152
|
+
else if (route._loadedRoutes) {
|
|
4153
|
+
return of({ routes: route._loadedRoutes, injector: route._loadedInjector });
|
|
3968
4154
|
}
|
|
3969
4155
|
if (this.onLoadStartListener) {
|
|
3970
4156
|
this.onLoadStartListener(route);
|
|
3971
4157
|
}
|
|
3972
|
-
const
|
|
3973
|
-
const loadRunner =
|
|
4158
|
+
const moduleFactoryOrRoutes$ = this.loadModuleFactoryOrRoutes(route.loadChildren);
|
|
4159
|
+
const loadRunner = moduleFactoryOrRoutes$.pipe(map((factoryOrRoutes) => {
|
|
3974
4160
|
if (this.onLoadEndListener) {
|
|
3975
4161
|
this.onLoadEndListener(route);
|
|
3976
4162
|
}
|
|
3977
|
-
|
|
3978
|
-
//
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
4163
|
+
// This injector comes from the `NgModuleRef` when lazy loading an `NgModule`. There is no
|
|
4164
|
+
// injector associated with lazy loading a `Route` array.
|
|
4165
|
+
let injector;
|
|
4166
|
+
let rawRoutes;
|
|
4167
|
+
let requireStandaloneComponents = false;
|
|
4168
|
+
if (Array.isArray(factoryOrRoutes)) {
|
|
4169
|
+
rawRoutes = factoryOrRoutes;
|
|
4170
|
+
requireStandaloneComponents = true;
|
|
4171
|
+
}
|
|
4172
|
+
else {
|
|
4173
|
+
injector = factoryOrRoutes.create(parentInjector).injector;
|
|
4174
|
+
// When loading a module that doesn't provide `RouterModule.forChild()` preloader
|
|
4175
|
+
// will get stuck in an infinite loop. The child module's Injector will look to
|
|
4176
|
+
// its parent `Injector` when it doesn't find any ROUTES so it will return routes
|
|
4177
|
+
// for it's parent module instead.
|
|
4178
|
+
rawRoutes = flatten(injector.get(ROUTES, [], InjectFlags.Self | InjectFlags.Optional));
|
|
4179
|
+
}
|
|
4180
|
+
const routes = rawRoutes.map(standardizeConfig);
|
|
4181
|
+
NG_DEV_MODE$1 && validateConfig(routes, route.path, requireStandaloneComponents);
|
|
4182
|
+
return { routes, injector };
|
|
4183
|
+
}), finalize(() => {
|
|
4184
|
+
this.childrenLoaders.delete(route);
|
|
3987
4185
|
}));
|
|
3988
4186
|
// Use custom ConnectableObservable as share in runners pipe increasing the bundle size too much
|
|
3989
|
-
|
|
4187
|
+
const loader = new ConnectableObservable(loadRunner, () => new Subject())
|
|
3990
4188
|
.pipe(refCount());
|
|
3991
|
-
|
|
4189
|
+
this.childrenLoaders.set(route, loader);
|
|
4190
|
+
return loader;
|
|
3992
4191
|
}
|
|
3993
|
-
|
|
4192
|
+
loadModuleFactoryOrRoutes(loadChildren) {
|
|
3994
4193
|
return wrapIntoObservable(loadChildren()).pipe(mergeMap((t) => {
|
|
3995
|
-
if (t instanceof NgModuleFactory) {
|
|
4194
|
+
if (t instanceof NgModuleFactory || Array.isArray(t)) {
|
|
3996
4195
|
return of(t);
|
|
3997
4196
|
}
|
|
3998
4197
|
else {
|
|
@@ -4001,6 +4200,11 @@ class RouterConfigLoader {
|
|
|
4001
4200
|
}));
|
|
4002
4201
|
}
|
|
4003
4202
|
}
|
|
4203
|
+
RouterConfigLoader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterConfigLoader, deps: [{ token: i0.Injector }, { token: i0.Compiler }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
4204
|
+
RouterConfigLoader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterConfigLoader });
|
|
4205
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterConfigLoader, decorators: [{
|
|
4206
|
+
type: Injectable
|
|
4207
|
+
}], ctorParameters: function () { return [{ type: i0.Injector }, { type: i0.Compiler }]; } });
|
|
4004
4208
|
|
|
4005
4209
|
/**
|
|
4006
4210
|
* @license
|
|
@@ -4033,6 +4237,7 @@ class DefaultUrlHandlingStrategy {
|
|
|
4033
4237
|
}
|
|
4034
4238
|
}
|
|
4035
4239
|
|
|
4240
|
+
const NG_DEV_MODE = typeof ngDevMode === 'undefined' || !!ngDevMode;
|
|
4036
4241
|
function defaultErrorHandler(error) {
|
|
4037
4242
|
throw error;
|
|
4038
4243
|
}
|
|
@@ -4175,6 +4380,8 @@ class Router {
|
|
|
4175
4380
|
/**
|
|
4176
4381
|
* Enables a bug fix that corrects relative link resolution in components with empty paths.
|
|
4177
4382
|
* @see `RouterModule`
|
|
4383
|
+
*
|
|
4384
|
+
* @deprecated
|
|
4178
4385
|
*/
|
|
4179
4386
|
this.relativeLinkResolution = 'corrected';
|
|
4180
4387
|
/**
|
|
@@ -4202,6 +4409,9 @@ class Router {
|
|
|
4202
4409
|
this.canceledNavigationResolution = 'replace';
|
|
4203
4410
|
const onLoadStart = (r) => this.triggerEvent(new RouteConfigLoadStart(r));
|
|
4204
4411
|
const onLoadEnd = (r) => this.triggerEvent(new RouteConfigLoadEnd(r));
|
|
4412
|
+
this.configLoader = injector.get(RouterConfigLoader);
|
|
4413
|
+
this.configLoader.onLoadEndListener = onLoadEnd;
|
|
4414
|
+
this.configLoader.onLoadStartListener = onLoadStart;
|
|
4205
4415
|
this.ngModule = injector.get(NgModuleRef);
|
|
4206
4416
|
this.console = injector.get(ɵConsole);
|
|
4207
4417
|
const ngZone = injector.get(NgZone);
|
|
@@ -4210,7 +4420,6 @@ class Router {
|
|
|
4210
4420
|
this.currentUrlTree = createEmptyUrlTree();
|
|
4211
4421
|
this.rawUrlTree = this.currentUrlTree;
|
|
4212
4422
|
this.browserUrlTree = this.currentUrlTree;
|
|
4213
|
-
this.configLoader = new RouterConfigLoader(injector, compiler, onLoadStart, onLoadEnd);
|
|
4214
4423
|
this.routerState = createEmptyState(this.currentUrlTree, this.rootComponentType);
|
|
4215
4424
|
this.transitions = new BehaviorSubject({
|
|
4216
4425
|
id: 0,
|
|
@@ -4408,6 +4617,26 @@ class Router {
|
|
|
4408
4617
|
skipLocationChange: !!skipLocationChange,
|
|
4409
4618
|
replaceUrl: !!replaceUrl,
|
|
4410
4619
|
});
|
|
4620
|
+
}),
|
|
4621
|
+
// --- LOAD COMPONENTS ---
|
|
4622
|
+
switchTap((t) => {
|
|
4623
|
+
const loadComponents = (route) => {
|
|
4624
|
+
var _a;
|
|
4625
|
+
const loaders = [];
|
|
4626
|
+
if (((_a = route.routeConfig) === null || _a === void 0 ? void 0 : _a.loadComponent) &&
|
|
4627
|
+
!route.routeConfig._loadedComponent) {
|
|
4628
|
+
loaders.push(this.configLoader.loadComponent(route.routeConfig)
|
|
4629
|
+
.pipe(tap(loadedComponent => {
|
|
4630
|
+
route.component = loadedComponent;
|
|
4631
|
+
}), map(() => void 0)));
|
|
4632
|
+
}
|
|
4633
|
+
for (const child of route.children) {
|
|
4634
|
+
loaders.push(...loadComponents(child));
|
|
4635
|
+
}
|
|
4636
|
+
return loaders;
|
|
4637
|
+
};
|
|
4638
|
+
return combineLatest(loadComponents(t.targetSnapshot.root))
|
|
4639
|
+
.pipe(defaultIfEmpty(), take(1));
|
|
4411
4640
|
}), map((t) => {
|
|
4412
4641
|
const targetRouterState = createRouterState(this.routeReuseStrategy, t.targetSnapshot, t.currentRouterState);
|
|
4413
4642
|
return (Object.assign(Object.assign({}, t), { targetRouterState }));
|
|
@@ -4487,23 +4716,17 @@ class Router {
|
|
|
4487
4716
|
t.resolve(false);
|
|
4488
4717
|
}
|
|
4489
4718
|
else {
|
|
4490
|
-
|
|
4491
|
-
|
|
4492
|
-
|
|
4493
|
-
|
|
4494
|
-
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
// the navigation is rejected.
|
|
4502
|
-
replaceUrl: this.urlUpdateStrategy === 'eager' ||
|
|
4503
|
-
isBrowserTriggeredNavigation(t.source)
|
|
4504
|
-
};
|
|
4505
|
-
this.scheduleNavigation(mergedTree, 'imperative', null, extras, { resolve: t.resolve, reject: t.reject, promise: t.promise });
|
|
4506
|
-
}, 0);
|
|
4719
|
+
const mergedTree = this.urlHandlingStrategy.merge(e.url, this.rawUrlTree);
|
|
4720
|
+
const extras = {
|
|
4721
|
+
skipLocationChange: t.extras.skipLocationChange,
|
|
4722
|
+
// The URL is already updated at this point if we have 'eager' URL
|
|
4723
|
+
// updates or if the navigation was triggered by the browser (back
|
|
4724
|
+
// button, URL bar, etc). We want to replace that item in history if
|
|
4725
|
+
// the navigation is rejected.
|
|
4726
|
+
replaceUrl: this.urlUpdateStrategy === 'eager' ||
|
|
4727
|
+
isBrowserTriggeredNavigation(t.source)
|
|
4728
|
+
};
|
|
4729
|
+
this.scheduleNavigation(mergedTree, 'imperative', null, extras, { resolve: t.resolve, reject: t.reject, promise: t.promise });
|
|
4507
4730
|
}
|
|
4508
4731
|
/* All other errors should reset to the router's internal URL reference to
|
|
4509
4732
|
* the pre-error state. */
|
|
@@ -4614,7 +4837,7 @@ class Router {
|
|
|
4614
4837
|
* ```
|
|
4615
4838
|
*/
|
|
4616
4839
|
resetConfig(config) {
|
|
4617
|
-
validateConfig(config);
|
|
4840
|
+
NG_DEV_MODE && validateConfig(config);
|
|
4618
4841
|
this.config = config.map(standardizeConfig);
|
|
4619
4842
|
this.navigated = false;
|
|
4620
4843
|
this.lastSuccessfulId = -1;
|
|
@@ -4972,9 +5195,9 @@ class Router {
|
|
|
4972
5195
|
return { navigationId };
|
|
4973
5196
|
}
|
|
4974
5197
|
}
|
|
4975
|
-
Router.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-
|
|
4976
|
-
Router.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-
|
|
4977
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-
|
|
5198
|
+
Router.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: Router, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
|
|
5199
|
+
Router.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: Router });
|
|
5200
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: Router, decorators: [{
|
|
4978
5201
|
type: Injectable
|
|
4979
5202
|
}], ctorParameters: function () { return [{ type: i0.Type }, { type: UrlSerializer }, { type: ChildrenOutletContexts }, { type: i3.Location }, { type: i0.Injector }, { type: i0.Compiler }, { type: undefined }]; } });
|
|
4980
5203
|
function validateCommands(commands) {
|
|
@@ -5166,9 +5389,9 @@ class RouterLink {
|
|
|
5166
5389
|
});
|
|
5167
5390
|
}
|
|
5168
5391
|
}
|
|
5169
|
-
RouterLink.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-
|
|
5170
|
-
RouterLink.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "
|
|
5171
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-
|
|
5392
|
+
RouterLink.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterLink, deps: [{ token: Router }, { token: ActivatedRoute }, { token: 'tabindex', attribute: true }, { token: i0.Renderer2 }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
|
|
5393
|
+
RouterLink.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.0.0-rc.2", 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 });
|
|
5394
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterLink, decorators: [{
|
|
5172
5395
|
type: Directive,
|
|
5173
5396
|
args: [{ selector: ':not(a):not(area)[routerLink]' }]
|
|
5174
5397
|
}], ctorParameters: function () {
|
|
@@ -5287,9 +5510,9 @@ class RouterLinkWithHref {
|
|
|
5287
5510
|
});
|
|
5288
5511
|
}
|
|
5289
5512
|
}
|
|
5290
|
-
RouterLinkWithHref.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-
|
|
5291
|
-
RouterLinkWithHref.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "
|
|
5292
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-
|
|
5513
|
+
RouterLinkWithHref.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterLinkWithHref, deps: [{ token: Router }, { token: ActivatedRoute }, { token: i3.LocationStrategy }], target: i0.ɵɵFactoryTarget.Directive });
|
|
5514
|
+
RouterLinkWithHref.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.0.0-rc.2", 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 });
|
|
5515
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterLinkWithHref, decorators: [{
|
|
5293
5516
|
type: Directive,
|
|
5294
5517
|
args: [{ selector: 'a[routerLink],area[routerLink]' }]
|
|
5295
5518
|
}], ctorParameters: function () { return [{ type: Router }, { type: ActivatedRoute }, { type: i3.LocationStrategy }]; }, propDecorators: { target: [{
|
|
@@ -5386,6 +5609,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9",
|
|
|
5386
5609
|
* </div>
|
|
5387
5610
|
* ```
|
|
5388
5611
|
*
|
|
5612
|
+
* The `RouterLinkActive` directive can also be used to set the aria-current attribute
|
|
5613
|
+
* to provide an alternative distinction for active elements to visually impaired users.
|
|
5614
|
+
*
|
|
5615
|
+
* For example, the following code adds the 'active' class to the Home Page link when it is
|
|
5616
|
+
* indeed active and in such case also sets its aria-current attribute to 'page':
|
|
5617
|
+
*
|
|
5618
|
+
* ```
|
|
5619
|
+
* <a routerLink="/" routerLinkActive="active" ariaCurrentWhenActive="page">Home Page</a>
|
|
5620
|
+
* ```
|
|
5621
|
+
*
|
|
5389
5622
|
* @ngModule RouterModule
|
|
5390
5623
|
*
|
|
5391
5624
|
* @publicApi
|
|
@@ -5481,6 +5714,12 @@ class RouterLinkActive {
|
|
|
5481
5714
|
this.renderer.removeClass(this.element.nativeElement, c);
|
|
5482
5715
|
}
|
|
5483
5716
|
});
|
|
5717
|
+
if (hasActiveLinks && this.ariaCurrentWhenActive !== undefined) {
|
|
5718
|
+
this.renderer.setAttribute(this.element.nativeElement, 'aria-current', this.ariaCurrentWhenActive.toString());
|
|
5719
|
+
}
|
|
5720
|
+
else {
|
|
5721
|
+
this.renderer.removeAttribute(this.element.nativeElement, 'aria-current');
|
|
5722
|
+
}
|
|
5484
5723
|
// Emit on isActiveChange after classes are updated
|
|
5485
5724
|
this.isActiveChange.emit(hasActiveLinks);
|
|
5486
5725
|
}
|
|
@@ -5500,9 +5739,9 @@ class RouterLinkActive {
|
|
|
5500
5739
|
this.links.some(isActiveCheckFn) || this.linksWithHrefs.some(isActiveCheckFn);
|
|
5501
5740
|
}
|
|
5502
5741
|
}
|
|
5503
|
-
RouterLinkActive.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-
|
|
5504
|
-
RouterLinkActive.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "
|
|
5505
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-
|
|
5742
|
+
RouterLinkActive.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.2", 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 });
|
|
5743
|
+
RouterLinkActive.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.0.0-rc.2", 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 });
|
|
5744
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterLinkActive, decorators: [{
|
|
5506
5745
|
type: Directive,
|
|
5507
5746
|
args: [{
|
|
5508
5747
|
selector: '[routerLinkActive]',
|
|
@@ -5522,6 +5761,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9",
|
|
|
5522
5761
|
args: [RouterLinkWithHref, { descendants: true }]
|
|
5523
5762
|
}], routerLinkActiveOptions: [{
|
|
5524
5763
|
type: Input
|
|
5764
|
+
}], ariaCurrentWhenActive: [{
|
|
5765
|
+
type: Input
|
|
5525
5766
|
}], isActiveChange: [{
|
|
5526
5767
|
type: Output
|
|
5527
5768
|
}], routerLinkActive: [{
|
|
@@ -5606,9 +5847,9 @@ class DefaultTitleStrategy extends TitleStrategy {
|
|
|
5606
5847
|
}
|
|
5607
5848
|
}
|
|
5608
5849
|
}
|
|
5609
|
-
DefaultTitleStrategy.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-
|
|
5610
|
-
DefaultTitleStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-
|
|
5611
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-
|
|
5850
|
+
DefaultTitleStrategy.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: DefaultTitleStrategy, deps: [{ token: i1.Title }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
5851
|
+
DefaultTitleStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: DefaultTitleStrategy, providedIn: 'root' });
|
|
5852
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: DefaultTitleStrategy, decorators: [{
|
|
5612
5853
|
type: Injectable,
|
|
5613
5854
|
args: [{ providedIn: 'root' }]
|
|
5614
5855
|
}], ctorParameters: function () { return [{ type: i1.Title }]; } });
|
|
@@ -5672,13 +5913,11 @@ class NoPreloading {
|
|
|
5672
5913
|
* @publicApi
|
|
5673
5914
|
*/
|
|
5674
5915
|
class RouterPreloader {
|
|
5675
|
-
constructor(router, compiler, injector, preloadingStrategy) {
|
|
5916
|
+
constructor(router, compiler, injector, preloadingStrategy, loader) {
|
|
5676
5917
|
this.router = router;
|
|
5677
5918
|
this.injector = injector;
|
|
5678
5919
|
this.preloadingStrategy = preloadingStrategy;
|
|
5679
|
-
|
|
5680
|
-
const onEndLoad = (r) => router.triggerEvent(new RouteConfigLoadEnd(r));
|
|
5681
|
-
this.loader = new RouterConfigLoader(injector, compiler, onStartLoad, onEndLoad);
|
|
5920
|
+
this.loader = loader;
|
|
5682
5921
|
}
|
|
5683
5922
|
setUpPreloading() {
|
|
5684
5923
|
this.subscription =
|
|
@@ -5687,8 +5926,7 @@ class RouterPreloader {
|
|
|
5687
5926
|
.subscribe(() => { });
|
|
5688
5927
|
}
|
|
5689
5928
|
preload() {
|
|
5690
|
-
|
|
5691
|
-
return this.processRoutes(ngModule, this.router.config);
|
|
5929
|
+
return this.processRoutes(this.injector, this.router.config);
|
|
5692
5930
|
}
|
|
5693
5931
|
/** @nodoc */
|
|
5694
5932
|
ngOnDestroy() {
|
|
@@ -5696,41 +5934,61 @@ class RouterPreloader {
|
|
|
5696
5934
|
this.subscription.unsubscribe();
|
|
5697
5935
|
}
|
|
5698
5936
|
}
|
|
5699
|
-
processRoutes(
|
|
5937
|
+
processRoutes(injector, routes) {
|
|
5938
|
+
var _a, _b, _c;
|
|
5700
5939
|
const res = [];
|
|
5701
5940
|
for (const route of routes) {
|
|
5702
|
-
|
|
5703
|
-
|
|
5704
|
-
|
|
5705
|
-
res.push(this.processRoutes(childConfig.module, childConfig.routes));
|
|
5706
|
-
// no config loaded, fetch the config
|
|
5941
|
+
if (route.providers && !route._injector) {
|
|
5942
|
+
route._injector =
|
|
5943
|
+
createEnvironmentInjector(route.providers, injector, `Route: ${route.path}`);
|
|
5707
5944
|
}
|
|
5708
|
-
|
|
5709
|
-
|
|
5710
|
-
|
|
5945
|
+
const injectorForCurrentRoute = (_a = route._injector) !== null && _a !== void 0 ? _a : injector;
|
|
5946
|
+
const injectorForChildren = (_b = route._loadedInjector) !== null && _b !== void 0 ? _b : injectorForCurrentRoute;
|
|
5947
|
+
if ((route.loadChildren && !route._loadedRoutes) ||
|
|
5948
|
+
(route.loadComponent && !route._loadedComponent)) {
|
|
5949
|
+
res.push(this.preloadConfig(injectorForCurrentRoute, route));
|
|
5711
5950
|
}
|
|
5712
|
-
else if (route.children) {
|
|
5713
|
-
res.push(this.processRoutes(
|
|
5951
|
+
else if (route.children || route._loadedRoutes) {
|
|
5952
|
+
res.push(this.processRoutes(injectorForChildren, ((_c = route.children) !== null && _c !== void 0 ? _c : route._loadedRoutes)));
|
|
5714
5953
|
}
|
|
5715
5954
|
}
|
|
5716
|
-
return from(res).pipe(mergeAll()
|
|
5955
|
+
return from(res).pipe(mergeAll());
|
|
5717
5956
|
}
|
|
5718
|
-
preloadConfig(
|
|
5957
|
+
preloadConfig(injector, route) {
|
|
5719
5958
|
return this.preloadingStrategy.preload(route, () => {
|
|
5720
|
-
|
|
5721
|
-
|
|
5722
|
-
|
|
5723
|
-
|
|
5724
|
-
|
|
5959
|
+
let loadedChildren$;
|
|
5960
|
+
if (route.loadChildren && route.canLoad === undefined) {
|
|
5961
|
+
loadedChildren$ = this.loader.loadChildren(injector, route);
|
|
5962
|
+
}
|
|
5963
|
+
else {
|
|
5964
|
+
loadedChildren$ = of(null);
|
|
5965
|
+
}
|
|
5966
|
+
const recursiveLoadChildren$ = loadedChildren$.pipe(mergeMap((config) => {
|
|
5967
|
+
var _a;
|
|
5968
|
+
if (config === null) {
|
|
5969
|
+
return of(void 0);
|
|
5970
|
+
}
|
|
5971
|
+
route._loadedRoutes = config.routes;
|
|
5972
|
+
route._loadedInjector = config.injector;
|
|
5973
|
+
// If the loaded config was a module, use that as the module/module injector going
|
|
5974
|
+
// forward. Otherwise, continue using the current module/module injector.
|
|
5975
|
+
return this.processRoutes((_a = config.injector) !== null && _a !== void 0 ? _a : injector, config.routes);
|
|
5725
5976
|
}));
|
|
5977
|
+
if (route.loadComponent && !route._loadedComponent) {
|
|
5978
|
+
const loadComponent$ = this.loader.loadComponent(route);
|
|
5979
|
+
return from([recursiveLoadChildren$, loadComponent$]).pipe(mergeAll());
|
|
5980
|
+
}
|
|
5981
|
+
else {
|
|
5982
|
+
return recursiveLoadChildren$;
|
|
5983
|
+
}
|
|
5726
5984
|
});
|
|
5727
5985
|
}
|
|
5728
5986
|
}
|
|
5729
|
-
RouterPreloader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-
|
|
5730
|
-
RouterPreloader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-
|
|
5731
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-
|
|
5987
|
+
RouterPreloader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterPreloader, deps: [{ token: Router }, { token: i0.Compiler }, { token: i0.EnvironmentInjector }, { token: PreloadingStrategy }, { token: RouterConfigLoader }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
5988
|
+
RouterPreloader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterPreloader });
|
|
5989
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterPreloader, decorators: [{
|
|
5732
5990
|
type: Injectable
|
|
5733
|
-
}], ctorParameters: function () { return [{ type: Router }, { type: i0.Compiler }, { type: i0.
|
|
5991
|
+
}], ctorParameters: function () { return [{ type: Router }, { type: i0.Compiler }, { type: i0.EnvironmentInjector }, { type: PreloadingStrategy }, { type: RouterConfigLoader }]; } });
|
|
5734
5992
|
|
|
5735
5993
|
class RouterScroller {
|
|
5736
5994
|
constructor(router,
|
|
@@ -5807,9 +6065,9 @@ class RouterScroller {
|
|
|
5807
6065
|
}
|
|
5808
6066
|
}
|
|
5809
6067
|
}
|
|
5810
|
-
RouterScroller.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-
|
|
5811
|
-
RouterScroller.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-
|
|
5812
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-
|
|
6068
|
+
RouterScroller.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterScroller, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
|
|
6069
|
+
RouterScroller.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterScroller });
|
|
6070
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterScroller, decorators: [{
|
|
5813
6071
|
type: Injectable
|
|
5814
6072
|
}], ctorParameters: function () { return [{ type: Router }, { type: i3.ViewportScroller }, { type: undefined }]; } });
|
|
5815
6073
|
|
|
@@ -5852,6 +6110,7 @@ const ROUTER_PROVIDERS = [
|
|
|
5852
6110
|
NoPreloading,
|
|
5853
6111
|
PreloadAllModules,
|
|
5854
6112
|
{ provide: ROUTER_CONFIGURATION, useValue: { enableTracing: false } },
|
|
6113
|
+
RouterConfigLoader,
|
|
5855
6114
|
];
|
|
5856
6115
|
function routerNgProbeToken() {
|
|
5857
6116
|
return new NgProbeToken('Router', Router);
|
|
@@ -5950,10 +6209,10 @@ class RouterModule {
|
|
|
5950
6209
|
return { ngModule: RouterModule, providers: [provideRoutes(routes)] };
|
|
5951
6210
|
}
|
|
5952
6211
|
}
|
|
5953
|
-
RouterModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-
|
|
5954
|
-
RouterModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "
|
|
5955
|
-
RouterModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.0-
|
|
5956
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-
|
|
6212
|
+
RouterModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterModule, deps: [{ token: ROUTER_FORROOT_GUARD, optional: true }, { token: Router, optional: true }], target: i0.ɵɵFactoryTarget.NgModule });
|
|
6213
|
+
RouterModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterModule, declarations: [RouterOutlet, RouterLink, RouterLinkWithHref, RouterLinkActive, ɵEmptyOutletComponent], exports: [RouterOutlet, RouterLink, RouterLinkWithHref, RouterLinkActive, ɵEmptyOutletComponent] });
|
|
6214
|
+
RouterModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterModule });
|
|
6215
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterModule, decorators: [{
|
|
5957
6216
|
type: NgModule,
|
|
5958
6217
|
args: [{
|
|
5959
6218
|
declarations: ROUTER_DIRECTIVES,
|
|
@@ -6017,12 +6276,12 @@ function setupRouter(urlSerializer, contexts, location, injector, compiler, conf
|
|
|
6017
6276
|
}
|
|
6018
6277
|
router.titleStrategy = titleStrategy !== null && titleStrategy !== void 0 ? titleStrategy : defaultTitleStrategy;
|
|
6019
6278
|
assignExtraOptionsToRouter(opts, router);
|
|
6020
|
-
if (opts.enableTracing) {
|
|
6279
|
+
if ((typeof ngDevMode === 'undefined' || ngDevMode) && opts.enableTracing) {
|
|
6021
6280
|
router.events.subscribe((e) => {
|
|
6022
6281
|
var _a, _b;
|
|
6023
6282
|
// tslint:disable:no-console
|
|
6024
6283
|
(_a = console.group) === null || _a === void 0 ? void 0 : _a.call(console, `Router Event: ${e.constructor.name}`);
|
|
6025
|
-
console.log(e
|
|
6284
|
+
console.log(stringifyEvent(e));
|
|
6026
6285
|
console.log(e);
|
|
6027
6286
|
(_b = console.groupEnd) === null || _b === void 0 ? void 0 : _b.call(console);
|
|
6028
6287
|
// tslint:enable:no-console
|
|
@@ -6089,9 +6348,7 @@ class RouterInitializer {
|
|
|
6089
6348
|
router.setUpLocationChangeListener();
|
|
6090
6349
|
resolve(true);
|
|
6091
6350
|
}
|
|
6092
|
-
else if (
|
|
6093
|
-
// TODO: enabled is deprecated as of v11, can be removed in v13
|
|
6094
|
-
opts.initialNavigation === 'enabled' || opts.initialNavigation === 'enabledBlocking') {
|
|
6351
|
+
else if (opts.initialNavigation === 'enabledBlocking') {
|
|
6095
6352
|
router.hooks.afterPreactivation = () => {
|
|
6096
6353
|
// only the initial navigation should be delayed
|
|
6097
6354
|
if (!this.initNavigation) {
|
|
@@ -6135,9 +6392,9 @@ class RouterInitializer {
|
|
|
6135
6392
|
this.destroyed = true;
|
|
6136
6393
|
}
|
|
6137
6394
|
}
|
|
6138
|
-
RouterInitializer.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-
|
|
6139
|
-
RouterInitializer.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-
|
|
6140
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-
|
|
6395
|
+
RouterInitializer.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterInitializer, deps: [{ token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
6396
|
+
RouterInitializer.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterInitializer });
|
|
6397
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterInitializer, decorators: [{
|
|
6141
6398
|
type: Injectable
|
|
6142
6399
|
}], ctorParameters: function () { return [{ type: i0.Injector }]; } });
|
|
6143
6400
|
function getAppInitializer(r) {
|
|
@@ -6177,7 +6434,7 @@ function provideRouterInitializer() {
|
|
|
6177
6434
|
/**
|
|
6178
6435
|
* @publicApi
|
|
6179
6436
|
*/
|
|
6180
|
-
const VERSION = new Version('14.0.0-
|
|
6437
|
+
const VERSION = new Version('14.0.0-rc.2');
|
|
6181
6438
|
|
|
6182
6439
|
/**
|
|
6183
6440
|
* @license
|