@angular/router 14.0.0-next.9 → 14.0.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2020/src/apply_redirects.mjs +57 -47
- package/esm2020/src/components/empty_outlet.mjs +3 -3
- package/esm2020/src/create_url_tree.mjs +25 -11
- package/esm2020/src/directives/router_link.mjs +6 -6
- package/esm2020/src/directives/router_link_active.mjs +22 -4
- package/esm2020/src/directives/router_outlet.mjs +25 -16
- package/esm2020/src/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 +71 -11
- package/esm2020/src/utils/config_matching.mjs +4 -1
- package/esm2020/src/utils/preactivation.mjs +5 -14
- package/esm2020/src/version.mjs +1 -1
- package/esm2020/testing/src/router_testing_module.mjs +4 -4
- package/fesm2015/router.mjs +917 -670
- package/fesm2015/router.mjs.map +1 -1
- package/fesm2015/testing.mjs +5 -5
- package/fesm2015/upgrade.mjs +1 -1
- package/fesm2020/router.mjs +902 -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/fesm2020/router.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular v14.0.0-
|
|
2
|
+
* @license Angular v14.0.0-rc.0
|
|
3
3
|
* (c) 2010-2022 Google LLC. https://angular.io/
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
import * as i3 from '@angular/common';
|
|
8
8
|
import { Location, LocationStrategy, PlatformLocation, APP_BASE_HREF, ViewportScroller, HashLocationStrategy, PathLocationStrategy, LOCATION_INITIALIZED } from '@angular/common';
|
|
9
9
|
import * as i0 from '@angular/core';
|
|
10
|
-
import { ɵisObservable, ɵisPromise, EventEmitter, Directive, Attribute, Output, Component,
|
|
10
|
+
import { ɵisObservable, ɵisPromise, EventEmitter, Directive, Attribute, Output, Component, ɵisStandalone, ComponentFactoryResolver, createEnvironmentInjector, InjectionToken, InjectFlags, NgModuleFactory, Injectable, NgModuleRef, ɵConsole, NgZone, ɵcoerceToBoolean, Input, HostListener, HostBinding, Optional, ContentChildren, Injector, Compiler, NgProbeToken, ANALYZE_FOR_ENTRY_COMPONENTS, SkipSelf, Inject, APP_INITIALIZER, APP_BOOTSTRAP_LISTENER, NgModule, ApplicationRef, Version } from '@angular/core';
|
|
11
11
|
import { from, of, BehaviorSubject, combineLatest, throwError, EmptyError, concat, defer, Observable, EMPTY, ConnectableObservable, Subject } from 'rxjs';
|
|
12
|
-
import { map, switchMap, take, startWith, scan, filter, catchError, concatMap, last as last$1, first, mergeMap, tap, takeLast,
|
|
12
|
+
import { map, switchMap, take, startWith, scan, filter, catchError, concatMap, last as last$1, first, mergeMap, tap, takeLast, mapTo, finalize, refCount, defaultIfEmpty, mergeAll } from 'rxjs/operators';
|
|
13
13
|
import * as i1 from '@angular/platform-browser';
|
|
14
14
|
|
|
15
15
|
/**
|
|
@@ -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,53 @@ 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
|
+
if (!('type' in routerEvent)) {
|
|
435
|
+
return `Unknown Router Event: ${routerEvent.constructor.name}`;
|
|
436
|
+
}
|
|
437
|
+
switch (routerEvent.type) {
|
|
438
|
+
case 14 /* EventType.ActivationEnd */:
|
|
439
|
+
return `ActivationEnd(path: '${routerEvent.snapshot.routeConfig?.path || ''}')`;
|
|
440
|
+
case 13 /* EventType.ActivationStart */:
|
|
441
|
+
return `ActivationStart(path: '${routerEvent.snapshot.routeConfig?.path || ''}')`;
|
|
442
|
+
case 12 /* EventType.ChildActivationEnd */:
|
|
443
|
+
return `ChildActivationEnd(path: '${routerEvent.snapshot.routeConfig?.path || ''}')`;
|
|
444
|
+
case 11 /* EventType.ChildActivationStart */:
|
|
445
|
+
return `ChildActivationStart(path: '${routerEvent.snapshot.routeConfig?.path || ''}')`;
|
|
446
|
+
case 8 /* EventType.GuardsCheckEnd */:
|
|
447
|
+
return `GuardsCheckEnd(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state}, shouldActivate: ${routerEvent.shouldActivate})`;
|
|
448
|
+
case 7 /* EventType.GuardsCheckStart */:
|
|
449
|
+
return `GuardsCheckStart(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`;
|
|
450
|
+
case 2 /* EventType.NavigationCancel */:
|
|
451
|
+
return `NavigationCancel(id: ${routerEvent.id}, url: '${routerEvent.url}')`;
|
|
452
|
+
case 1 /* EventType.NavigationEnd */:
|
|
453
|
+
return `NavigationEnd(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}')`;
|
|
454
|
+
case 3 /* EventType.NavigationError */:
|
|
455
|
+
return `NavigationError(id: ${routerEvent.id}, url: '${routerEvent.url}', error: ${routerEvent.error})`;
|
|
456
|
+
case 0 /* EventType.NavigationStart */:
|
|
457
|
+
return `NavigationStart(id: ${routerEvent.id}, url: '${routerEvent.url}')`;
|
|
458
|
+
case 6 /* EventType.ResolveEnd */:
|
|
459
|
+
return `ResolveEnd(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`;
|
|
460
|
+
case 5 /* EventType.ResolveStart */:
|
|
461
|
+
return `ResolveStart(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`;
|
|
462
|
+
case 10 /* EventType.RouteConfigLoadEnd */:
|
|
463
|
+
return `RouteConfigLoadEnd(path: ${routerEvent.route.path})`;
|
|
464
|
+
case 9 /* EventType.RouteConfigLoadStart */:
|
|
465
|
+
return `RouteConfigLoadStart(path: ${routerEvent.route.path})`;
|
|
466
|
+
case 4 /* EventType.RoutesRecognized */:
|
|
467
|
+
return `RoutesRecognized(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`;
|
|
468
|
+
case 15 /* EventType.Scroll */:
|
|
469
|
+
const pos = routerEvent.position ? `${routerEvent.position[0]}, ${routerEvent.position[1]}` : null;
|
|
470
|
+
return `Scroll(anchor: '${routerEvent.anchor}', position: '${pos}')`;
|
|
471
|
+
}
|
|
472
|
+
}
|
|
417
473
|
|
|
418
474
|
/**
|
|
419
475
|
* @license
|
|
@@ -1362,7 +1418,6 @@ class ActivatedRoute {
|
|
|
1362
1418
|
/** The outlet name of the route, a constant. */
|
|
1363
1419
|
outlet,
|
|
1364
1420
|
/** The component of the route, a constant. */
|
|
1365
|
-
// TODO(vsavkin): remove |string
|
|
1366
1421
|
component, futureSnapshot) {
|
|
1367
1422
|
this.url = url;
|
|
1368
1423
|
this.params = params;
|
|
@@ -1456,7 +1511,7 @@ function flattenInherited(pathFromRoot) {
|
|
|
1456
1511
|
return pathFromRoot.reduce((res, curr) => {
|
|
1457
1512
|
const params = { ...res.params, ...curr.params };
|
|
1458
1513
|
const data = { ...res.data, ...curr.data };
|
|
1459
|
-
const resolve = { ...res.resolve, ...curr._resolvedData };
|
|
1514
|
+
const resolve = { ...curr.data, ...res.resolve, ...curr.routeConfig?.data, ...curr._resolvedData };
|
|
1460
1515
|
return { params, data, resolve };
|
|
1461
1516
|
}, { params: {}, data: {}, resolve: {} });
|
|
1462
1517
|
}
|
|
@@ -1517,7 +1572,7 @@ class ActivatedRouteSnapshot {
|
|
|
1517
1572
|
/** The outlet name of the route */
|
|
1518
1573
|
outlet,
|
|
1519
1574
|
/** The component of the route */
|
|
1520
|
-
component, routeConfig, urlSegment, lastPathIndex, resolve) {
|
|
1575
|
+
component, routeConfig, urlSegment, lastPathIndex, resolve, correctedLastPathIndex) {
|
|
1521
1576
|
this.url = url;
|
|
1522
1577
|
this.params = params;
|
|
1523
1578
|
this.queryParams = queryParams;
|
|
@@ -1528,6 +1583,7 @@ class ActivatedRouteSnapshot {
|
|
|
1528
1583
|
this.routeConfig = routeConfig;
|
|
1529
1584
|
this._urlSegment = urlSegment;
|
|
1530
1585
|
this._lastPathIndex = lastPathIndex;
|
|
1586
|
+
this._correctedLastPathIndex = correctedLastPathIndex ?? lastPathIndex;
|
|
1531
1587
|
this._resolve = resolve;
|
|
1532
1588
|
}
|
|
1533
1589
|
/** The root of the router state */
|
|
@@ -1719,11 +1775,26 @@ function createUrlTree(route, urlTree, commands, queryParams, fragment) {
|
|
|
1719
1775
|
if (nav.toRoot()) {
|
|
1720
1776
|
return tree(urlTree.root, urlTree.root, new UrlSegmentGroup([], {}), queryParams, fragment);
|
|
1721
1777
|
}
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1778
|
+
function createTreeUsingPathIndex(lastPathIndex) {
|
|
1779
|
+
const startingPosition = findStartingPosition(nav, urlTree, route.snapshot?._urlSegment, lastPathIndex);
|
|
1780
|
+
const segmentGroup = startingPosition.processChildren ?
|
|
1781
|
+
updateSegmentGroupChildren(startingPosition.segmentGroup, startingPosition.index, nav.commands) :
|
|
1782
|
+
updateSegmentGroup(startingPosition.segmentGroup, startingPosition.index, nav.commands);
|
|
1783
|
+
return tree(urlTree.root, startingPosition.segmentGroup, segmentGroup, queryParams, fragment);
|
|
1784
|
+
}
|
|
1785
|
+
// Note: The types should disallow `snapshot` from being `undefined` but due to test mocks, this
|
|
1786
|
+
// may be the case. Since we try to access it at an earlier point before the refactor to add the
|
|
1787
|
+
// warning for `relativeLinkResolution: 'legacy'`, this may cause failures in tests where it
|
|
1788
|
+
// didn't before.
|
|
1789
|
+
const result = createTreeUsingPathIndex(route.snapshot?._lastPathIndex);
|
|
1790
|
+
// Check if application is relying on `relativeLinkResolution: 'legacy'`
|
|
1791
|
+
if (typeof ngDevMode === 'undefined' || !!ngDevMode) {
|
|
1792
|
+
const correctedResult = createTreeUsingPathIndex(route.snapshot?._correctedLastPathIndex);
|
|
1793
|
+
if (correctedResult.toString() !== result.toString()) {
|
|
1794
|
+
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.`);
|
|
1795
|
+
}
|
|
1796
|
+
}
|
|
1797
|
+
return result;
|
|
1727
1798
|
}
|
|
1728
1799
|
function isMatrixParams(command) {
|
|
1729
1800
|
return typeof command === 'object' && command != null && !command.outlets && !command.segmentPath;
|
|
@@ -1828,12 +1899,11 @@ class Position {
|
|
|
1828
1899
|
this.index = index;
|
|
1829
1900
|
}
|
|
1830
1901
|
}
|
|
1831
|
-
function findStartingPosition(nav, tree,
|
|
1902
|
+
function findStartingPosition(nav, tree, segmentGroup, lastPathIndex) {
|
|
1832
1903
|
if (nav.isAbsolute) {
|
|
1833
1904
|
return new Position(tree.root, true, 0);
|
|
1834
1905
|
}
|
|
1835
|
-
if (
|
|
1836
|
-
const segmentGroup = route.snapshot._urlSegment;
|
|
1906
|
+
if (lastPathIndex === -1) {
|
|
1837
1907
|
// Pathless ActivatedRoute has _lastPathIndex === -1 but should not process children
|
|
1838
1908
|
// see issue #26224, #13011, #35687
|
|
1839
1909
|
// However, if the ActivatedRoute is the root we should process children like above.
|
|
@@ -1841,8 +1911,8 @@ function findStartingPosition(nav, tree, route) {
|
|
|
1841
1911
|
return new Position(segmentGroup, processChildren, 0);
|
|
1842
1912
|
}
|
|
1843
1913
|
const modifier = isMatrixParams(nav.commands[0]) ? 0 : 1;
|
|
1844
|
-
const index =
|
|
1845
|
-
return createPositionApplyingDoubleDots(
|
|
1914
|
+
const index = lastPathIndex + modifier;
|
|
1915
|
+
return createPositionApplyingDoubleDots(segmentGroup, index, nav.numberOfDoubleDots);
|
|
1846
1916
|
}
|
|
1847
1917
|
function createPositionApplyingDoubleDots(group, index, numberOfDoubleDots) {
|
|
1848
1918
|
let g = group;
|
|
@@ -2005,181 +2075,76 @@ function compare(path, params, segment) {
|
|
|
2005
2075
|
* Use of this source code is governed by an MIT-style license that can be
|
|
2006
2076
|
* found in the LICENSE file at https://angular.io/license
|
|
2007
2077
|
*/
|
|
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
|
-
}
|
|
2078
|
+
/**
|
|
2079
|
+
* Store contextual information about a `RouterOutlet`
|
|
2080
|
+
*
|
|
2081
|
+
* @publicApi
|
|
2082
|
+
*/
|
|
2083
|
+
class OutletContext {
|
|
2084
|
+
constructor() {
|
|
2085
|
+
this.outlet = null;
|
|
2086
|
+
this.route = null;
|
|
2087
|
+
/**
|
|
2088
|
+
* @deprecated Passing a resolver to retrieve a component factory is not required and is
|
|
2089
|
+
* deprecated since v14.
|
|
2090
|
+
*/
|
|
2091
|
+
this.resolver = null;
|
|
2092
|
+
this.injector = null;
|
|
2093
|
+
this.children = new ChildrenOutletContexts();
|
|
2094
|
+
this.attachRef = null;
|
|
2064
2095
|
}
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2096
|
+
}
|
|
2097
|
+
/**
|
|
2098
|
+
* Store contextual information about the children (= nested) `RouterOutlet`
|
|
2099
|
+
*
|
|
2100
|
+
* @publicApi
|
|
2101
|
+
*/
|
|
2102
|
+
class ChildrenOutletContexts {
|
|
2103
|
+
constructor() {
|
|
2104
|
+
// contexts for child outlets, by name.
|
|
2105
|
+
this.contexts = new Map();
|
|
2074
2106
|
}
|
|
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
|
-
}
|
|
2107
|
+
/** Called when a `RouterOutlet` directive is instantiated */
|
|
2108
|
+
onChildOutletCreated(childName, outlet) {
|
|
2109
|
+
const context = this.getOrCreateContext(childName);
|
|
2110
|
+
context.outlet = outlet;
|
|
2111
|
+
this.contexts.set(childName, context);
|
|
2087
2112
|
}
|
|
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.
|
|
2113
|
+
/**
|
|
2114
|
+
* Called when a `RouterOutlet` directive is destroyed.
|
|
2115
|
+
* We need to keep the context as the outlet could be destroyed inside a NgIf and might be
|
|
2116
|
+
* re-created later.
|
|
2117
|
+
*/
|
|
2118
|
+
onChildOutletDestroyed(childName) {
|
|
2119
|
+
const context = this.getContext(childName);
|
|
2120
|
+
if (context) {
|
|
2121
|
+
context.outlet = null;
|
|
2104
2122
|
context.attachRef = null;
|
|
2105
|
-
context.resolver = null;
|
|
2106
|
-
context.route = null;
|
|
2107
2123
|
}
|
|
2108
2124
|
}
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
}
|
|
2125
|
+
/**
|
|
2126
|
+
* Called when the corresponding route is deactivated during navigation.
|
|
2127
|
+
* Because the component get destroyed, all children outlet are destroyed.
|
|
2128
|
+
*/
|
|
2129
|
+
onOutletDeactivated() {
|
|
2130
|
+
const contexts = this.contexts;
|
|
2131
|
+
this.contexts = new Map();
|
|
2132
|
+
return contexts;
|
|
2118
2133
|
}
|
|
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
|
-
}
|
|
2134
|
+
onOutletReAttached(contexts) {
|
|
2135
|
+
this.contexts = contexts;
|
|
2136
|
+
}
|
|
2137
|
+
getOrCreateContext(childName) {
|
|
2138
|
+
let context = this.getContext(childName);
|
|
2139
|
+
if (!context) {
|
|
2140
|
+
context = new OutletContext();
|
|
2141
|
+
this.contexts.set(childName, context);
|
|
2171
2142
|
}
|
|
2143
|
+
return context;
|
|
2172
2144
|
}
|
|
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;
|
|
2145
|
+
getContext(childName) {
|
|
2146
|
+
return this.contexts.get(childName) || null;
|
|
2181
2147
|
}
|
|
2182
|
-
return null;
|
|
2183
2148
|
}
|
|
2184
2149
|
|
|
2185
2150
|
/**
|
|
@@ -2189,182 +2154,13 @@ function parentLoadedConfig(snapshot) {
|
|
|
2189
2154
|
* Use of this source code is governed by an MIT-style license that can be
|
|
2190
2155
|
* found in the LICENSE file at https://angular.io/license
|
|
2191
2156
|
*/
|
|
2192
|
-
class LoadedRouterConfig {
|
|
2193
|
-
constructor(routes, module) {
|
|
2194
|
-
this.routes = routes;
|
|
2195
|
-
this.module = module;
|
|
2196
|
-
}
|
|
2197
|
-
}
|
|
2198
|
-
|
|
2199
2157
|
/**
|
|
2200
|
-
* @
|
|
2201
|
-
* Copyright Google LLC All Rights Reserved.
|
|
2158
|
+
* @description
|
|
2202
2159
|
*
|
|
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:
|
|
2160
|
+
* Acts as a placeholder that Angular dynamically fills based on the current router state.
|
|
2208
2161
|
*
|
|
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".
|
|
2162
|
+
* Each outlet can have a unique name, determined by the optional `name` attribute.
|
|
2163
|
+
* The name cannot be set or changed dynamically. If not set, default value is "primary".
|
|
2368
2164
|
*
|
|
2369
2165
|
* ```
|
|
2370
2166
|
* <router-outlet></router-outlet>
|
|
@@ -2410,11 +2206,11 @@ class ChildrenOutletContexts {
|
|
|
2410
2206
|
* @publicApi
|
|
2411
2207
|
*/
|
|
2412
2208
|
class RouterOutlet {
|
|
2413
|
-
constructor(parentContexts, location,
|
|
2209
|
+
constructor(parentContexts, location, name, changeDetector, environmentInjector) {
|
|
2414
2210
|
this.parentContexts = parentContexts;
|
|
2415
2211
|
this.location = location;
|
|
2416
|
-
this.resolver = resolver;
|
|
2417
2212
|
this.changeDetector = changeDetector;
|
|
2213
|
+
this.environmentInjector = environmentInjector;
|
|
2418
2214
|
this.activated = null;
|
|
2419
2215
|
this._activatedRoute = null;
|
|
2420
2216
|
this.activateEvents = new EventEmitter();
|
|
@@ -2449,7 +2245,7 @@ class RouterOutlet {
|
|
|
2449
2245
|
}
|
|
2450
2246
|
else {
|
|
2451
2247
|
// otherwise the component defined in the configuration is created
|
|
2452
|
-
this.activateWith(context.route, context.
|
|
2248
|
+
this.activateWith(context.route, context.injector);
|
|
2453
2249
|
}
|
|
2454
2250
|
}
|
|
2455
2251
|
}
|
|
@@ -2508,33 +2304,39 @@ class RouterOutlet {
|
|
|
2508
2304
|
this.deactivateEvents.emit(c);
|
|
2509
2305
|
}
|
|
2510
2306
|
}
|
|
2511
|
-
activateWith(activatedRoute,
|
|
2307
|
+
activateWith(activatedRoute, resolverOrInjector) {
|
|
2512
2308
|
if (this.isActivated) {
|
|
2513
2309
|
throw new Error('Cannot activate an already activated outlet');
|
|
2514
2310
|
}
|
|
2515
2311
|
this._activatedRoute = activatedRoute;
|
|
2312
|
+
const location = this.location;
|
|
2516
2313
|
const snapshot = activatedRoute._futureSnapshot;
|
|
2517
|
-
const component = snapshot.
|
|
2518
|
-
resolver = resolver || this.resolver;
|
|
2519
|
-
const factory = resolver.resolveComponentFactory(component);
|
|
2314
|
+
const component = snapshot.component;
|
|
2520
2315
|
const childContexts = this.parentContexts.getOrCreateContext(this.name).children;
|
|
2521
|
-
const injector = new OutletInjector(activatedRoute, childContexts,
|
|
2522
|
-
|
|
2316
|
+
const injector = new OutletInjector(activatedRoute, childContexts, location.injector);
|
|
2317
|
+
if (resolverOrInjector && isComponentFactoryResolver(resolverOrInjector)) {
|
|
2318
|
+
const factory = resolverOrInjector.resolveComponentFactory(component);
|
|
2319
|
+
this.activated = location.createComponent(factory, location.length, injector);
|
|
2320
|
+
}
|
|
2321
|
+
else {
|
|
2322
|
+
const environmentInjector = resolverOrInjector ?? this.environmentInjector;
|
|
2323
|
+
this.activated = location.createComponent(component, { index: location.length, injector, environmentInjector });
|
|
2324
|
+
}
|
|
2523
2325
|
// Calling `markForCheck` to make sure we will run the change detection when the
|
|
2524
2326
|
// `RouterOutlet` is inside a `ChangeDetectionStrategy.OnPush` component.
|
|
2525
2327
|
this.changeDetector.markForCheck();
|
|
2526
2328
|
this.activateEvents.emit(this.activated.instance);
|
|
2527
2329
|
}
|
|
2528
2330
|
}
|
|
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-
|
|
2331
|
+
RouterOutlet.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.0", ngImport: i0, type: RouterOutlet, deps: [{ token: ChildrenOutletContexts }, { token: i0.ViewContainerRef }, { token: 'name', attribute: true }, { token: i0.ChangeDetectorRef }, { token: i0.EnvironmentInjector }], target: i0.ɵɵFactoryTarget.Directive });
|
|
2332
|
+
RouterOutlet.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.0.0-rc.0", type: RouterOutlet, selector: "router-outlet", outputs: { activateEvents: "activate", deactivateEvents: "deactivate", attachEvents: "attach", detachEvents: "detach" }, exportAs: ["outlet"], ngImport: i0 });
|
|
2333
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.0", ngImport: i0, type: RouterOutlet, decorators: [{
|
|
2532
2334
|
type: Directive,
|
|
2533
2335
|
args: [{ selector: 'router-outlet', exportAs: 'outlet' }]
|
|
2534
|
-
}], ctorParameters: function () { return [{ type: ChildrenOutletContexts }, { type: i0.ViewContainerRef }, { type:
|
|
2336
|
+
}], ctorParameters: function () { return [{ type: ChildrenOutletContexts }, { type: i0.ViewContainerRef }, { type: undefined, decorators: [{
|
|
2535
2337
|
type: Attribute,
|
|
2536
2338
|
args: ['name']
|
|
2537
|
-
}] }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { activateEvents: [{
|
|
2339
|
+
}] }, { type: i0.ChangeDetectorRef }, { type: i0.EnvironmentInjector }]; }, propDecorators: { activateEvents: [{
|
|
2538
2340
|
type: Output,
|
|
2539
2341
|
args: ['activate']
|
|
2540
2342
|
}], deactivateEvents: [{
|
|
@@ -2560,7 +2362,385 @@ class OutletInjector {
|
|
|
2560
2362
|
if (token === ChildrenOutletContexts) {
|
|
2561
2363
|
return this.childContexts;
|
|
2562
2364
|
}
|
|
2563
|
-
return this.parent.get(token, notFoundValue);
|
|
2365
|
+
return this.parent.get(token, notFoundValue);
|
|
2366
|
+
}
|
|
2367
|
+
}
|
|
2368
|
+
function isComponentFactoryResolver(item) {
|
|
2369
|
+
return !!item.resolveComponentFactory;
|
|
2370
|
+
}
|
|
2371
|
+
|
|
2372
|
+
/**
|
|
2373
|
+
* @license
|
|
2374
|
+
* Copyright Google LLC All Rights Reserved.
|
|
2375
|
+
*
|
|
2376
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
2377
|
+
* found in the LICENSE file at https://angular.io/license
|
|
2378
|
+
*/
|
|
2379
|
+
/**
|
|
2380
|
+
* This component is used internally within the router to be a placeholder when an empty
|
|
2381
|
+
* router-outlet is needed. For example, with a config such as:
|
|
2382
|
+
*
|
|
2383
|
+
* `{path: 'parent', outlet: 'nav', children: [...]}`
|
|
2384
|
+
*
|
|
2385
|
+
* In order to render, there needs to be a component on this config, which will default
|
|
2386
|
+
* to this `EmptyOutletComponent`.
|
|
2387
|
+
*/
|
|
2388
|
+
class ɵEmptyOutletComponent {
|
|
2389
|
+
}
|
|
2390
|
+
ɵEmptyOutletComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.0", ngImport: i0, type: ɵEmptyOutletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2391
|
+
ɵEmptyOutletComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.0-rc.0", 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"] }] });
|
|
2392
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.0", ngImport: i0, type: ɵEmptyOutletComponent, decorators: [{
|
|
2393
|
+
type: Component,
|
|
2394
|
+
args: [{ template: `<router-outlet></router-outlet>` }]
|
|
2395
|
+
}] });
|
|
2396
|
+
|
|
2397
|
+
/**
|
|
2398
|
+
* @license
|
|
2399
|
+
* Copyright Google LLC All Rights Reserved.
|
|
2400
|
+
*
|
|
2401
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
2402
|
+
* found in the LICENSE file at https://angular.io/license
|
|
2403
|
+
*/
|
|
2404
|
+
function getLoadedRoutes(route) {
|
|
2405
|
+
return route._loadedRoutes;
|
|
2406
|
+
}
|
|
2407
|
+
function getLoadedInjector(route) {
|
|
2408
|
+
return route._loadedInjector;
|
|
2409
|
+
}
|
|
2410
|
+
function getLoadedComponent(route) {
|
|
2411
|
+
return route._loadedComponent;
|
|
2412
|
+
}
|
|
2413
|
+
function getProvidersInjector(route) {
|
|
2414
|
+
return route._injector;
|
|
2415
|
+
}
|
|
2416
|
+
function validateConfig(config, parentPath = '', requireStandaloneComponents = false) {
|
|
2417
|
+
// forEach doesn't iterate undefined values
|
|
2418
|
+
for (let i = 0; i < config.length; i++) {
|
|
2419
|
+
const route = config[i];
|
|
2420
|
+
const fullPath = getFullPath(parentPath, route);
|
|
2421
|
+
validateNode(route, fullPath, requireStandaloneComponents);
|
|
2422
|
+
}
|
|
2423
|
+
}
|
|
2424
|
+
function assertStandalone(fullPath, component) {
|
|
2425
|
+
if (component && !ɵisStandalone(component)) {
|
|
2426
|
+
throw new Error(`Invalid configuration of route '${fullPath}'. The component must be standalone.`);
|
|
2427
|
+
}
|
|
2428
|
+
}
|
|
2429
|
+
function validateNode(route, fullPath, requireStandaloneComponents) {
|
|
2430
|
+
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
2431
|
+
if (!route) {
|
|
2432
|
+
throw new Error(`
|
|
2433
|
+
Invalid configuration of route '${fullPath}': Encountered undefined route.
|
|
2434
|
+
The reason might be an extra comma.
|
|
2435
|
+
|
|
2436
|
+
Example:
|
|
2437
|
+
const routes: Routes = [
|
|
2438
|
+
{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },
|
|
2439
|
+
{ path: 'dashboard', component: DashboardComponent },, << two commas
|
|
2440
|
+
{ path: 'detail/:id', component: HeroDetailComponent }
|
|
2441
|
+
];
|
|
2442
|
+
`);
|
|
2443
|
+
}
|
|
2444
|
+
if (Array.isArray(route)) {
|
|
2445
|
+
throw new Error(`Invalid configuration of route '${fullPath}': Array cannot be specified`);
|
|
2446
|
+
}
|
|
2447
|
+
if (!route.component && !route.loadComponent && !route.children && !route.loadChildren &&
|
|
2448
|
+
(route.outlet && route.outlet !== PRIMARY_OUTLET)) {
|
|
2449
|
+
throw new Error(`Invalid configuration of route '${fullPath}': a componentless route without children or loadChildren cannot have a named outlet set`);
|
|
2450
|
+
}
|
|
2451
|
+
if (route.redirectTo && route.children) {
|
|
2452
|
+
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and children cannot be used together`);
|
|
2453
|
+
}
|
|
2454
|
+
if (route.redirectTo && route.loadChildren) {
|
|
2455
|
+
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and loadChildren cannot be used together`);
|
|
2456
|
+
}
|
|
2457
|
+
if (route.children && route.loadChildren) {
|
|
2458
|
+
throw new Error(`Invalid configuration of route '${fullPath}': children and loadChildren cannot be used together`);
|
|
2459
|
+
}
|
|
2460
|
+
if (route.redirectTo && (route.component || route.loadComponent)) {
|
|
2461
|
+
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and component/loadComponent cannot be used together`);
|
|
2462
|
+
}
|
|
2463
|
+
if (route.component && route.loadComponent) {
|
|
2464
|
+
throw new Error(`Invalid configuration of route '${fullPath}': component and loadComponent cannot be used together`);
|
|
2465
|
+
}
|
|
2466
|
+
if (route.redirectTo && route.canActivate) {
|
|
2467
|
+
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and canActivate cannot be used together. Redirects happen before activation ` +
|
|
2468
|
+
`so canActivate will never be executed.`);
|
|
2469
|
+
}
|
|
2470
|
+
if (route.path && route.matcher) {
|
|
2471
|
+
throw new Error(`Invalid configuration of route '${fullPath}': path and matcher cannot be used together`);
|
|
2472
|
+
}
|
|
2473
|
+
if (route.redirectTo === void 0 && !route.component && !route.loadComponent &&
|
|
2474
|
+
!route.children && !route.loadChildren) {
|
|
2475
|
+
throw new Error(`Invalid configuration of route '${fullPath}'. One of the following must be provided: component, loadComponent, redirectTo, children or loadChildren`);
|
|
2476
|
+
}
|
|
2477
|
+
if (route.path === void 0 && route.matcher === void 0) {
|
|
2478
|
+
throw new Error(`Invalid configuration of route '${fullPath}': routes must have either a path or a matcher specified`);
|
|
2479
|
+
}
|
|
2480
|
+
if (typeof route.path === 'string' && route.path.charAt(0) === '/') {
|
|
2481
|
+
throw new Error(`Invalid configuration of route '${fullPath}': path cannot start with a slash`);
|
|
2482
|
+
}
|
|
2483
|
+
if (route.path === '' && route.redirectTo !== void 0 && route.pathMatch === void 0) {
|
|
2484
|
+
const exp = `The default value of 'pathMatch' is 'prefix', but often the intent is to use 'full'.`;
|
|
2485
|
+
throw new Error(`Invalid configuration of route '{path: "${fullPath}", redirectTo: "${route.redirectTo}"}': please provide 'pathMatch'. ${exp}`);
|
|
2486
|
+
}
|
|
2487
|
+
if (requireStandaloneComponents) {
|
|
2488
|
+
assertStandalone(fullPath, route.component);
|
|
2489
|
+
}
|
|
2490
|
+
}
|
|
2491
|
+
if (route.children) {
|
|
2492
|
+
validateConfig(route.children, fullPath, requireStandaloneComponents);
|
|
2493
|
+
}
|
|
2494
|
+
}
|
|
2495
|
+
function getFullPath(parentPath, currentRoute) {
|
|
2496
|
+
if (!currentRoute) {
|
|
2497
|
+
return parentPath;
|
|
2498
|
+
}
|
|
2499
|
+
if (!parentPath && !currentRoute.path) {
|
|
2500
|
+
return '';
|
|
2501
|
+
}
|
|
2502
|
+
else if (parentPath && !currentRoute.path) {
|
|
2503
|
+
return `${parentPath}/`;
|
|
2504
|
+
}
|
|
2505
|
+
else if (!parentPath && currentRoute.path) {
|
|
2506
|
+
return currentRoute.path;
|
|
2507
|
+
}
|
|
2508
|
+
else {
|
|
2509
|
+
return `${parentPath}/${currentRoute.path}`;
|
|
2510
|
+
}
|
|
2511
|
+
}
|
|
2512
|
+
/**
|
|
2513
|
+
* Makes a copy of the config and adds any default required properties.
|
|
2514
|
+
*/
|
|
2515
|
+
function standardizeConfig(r) {
|
|
2516
|
+
const children = r.children && r.children.map(standardizeConfig);
|
|
2517
|
+
const c = children ? { ...r, children } : { ...r };
|
|
2518
|
+
if ((!c.component && !c.loadComponent) && (children || c.loadChildren) &&
|
|
2519
|
+
(c.outlet && c.outlet !== PRIMARY_OUTLET)) {
|
|
2520
|
+
c.component = ɵEmptyOutletComponent;
|
|
2521
|
+
}
|
|
2522
|
+
return c;
|
|
2523
|
+
}
|
|
2524
|
+
/** Returns the `route.outlet` or PRIMARY_OUTLET if none exists. */
|
|
2525
|
+
function getOutlet(route) {
|
|
2526
|
+
return route.outlet || PRIMARY_OUTLET;
|
|
2527
|
+
}
|
|
2528
|
+
/**
|
|
2529
|
+
* Sorts the `routes` such that the ones with an outlet matching `outletName` come first.
|
|
2530
|
+
* The order of the configs is otherwise preserved.
|
|
2531
|
+
*/
|
|
2532
|
+
function sortByMatchingOutlets(routes, outletName) {
|
|
2533
|
+
const sortedConfig = routes.filter(r => getOutlet(r) === outletName);
|
|
2534
|
+
sortedConfig.push(...routes.filter(r => getOutlet(r) !== outletName));
|
|
2535
|
+
return sortedConfig;
|
|
2536
|
+
}
|
|
2537
|
+
/**
|
|
2538
|
+
* Gets the first injector in the snapshot's parent tree.
|
|
2539
|
+
*
|
|
2540
|
+
* If the `Route` has a static list of providers, the returned injector will be the one created from
|
|
2541
|
+
* those. If it does not exist, the returned injector may come from the parents, which may be from a
|
|
2542
|
+
* loaded config or their static providers.
|
|
2543
|
+
*
|
|
2544
|
+
* Returns `null` if there is neither this nor any parents have a stored injector.
|
|
2545
|
+
*
|
|
2546
|
+
* Generally used for retrieving the injector to use for getting tokens for guards/resolvers and
|
|
2547
|
+
* also used for getting the correct injector to use for creating components.
|
|
2548
|
+
*/
|
|
2549
|
+
function getClosestRouteInjector(snapshot) {
|
|
2550
|
+
if (!snapshot)
|
|
2551
|
+
return null;
|
|
2552
|
+
// If the current route has its own injector, which is created from the static providers on the
|
|
2553
|
+
// route itself, we should use that. Otherwise, we start at the parent since we do not want to
|
|
2554
|
+
// include the lazy loaded injector from this route.
|
|
2555
|
+
if (snapshot.routeConfig?._injector) {
|
|
2556
|
+
return snapshot.routeConfig._injector;
|
|
2557
|
+
}
|
|
2558
|
+
for (let s = snapshot.parent; s; s = s.parent) {
|
|
2559
|
+
const route = s.routeConfig;
|
|
2560
|
+
// Note that the order here is important. `_loadedInjector` stored on the route with
|
|
2561
|
+
// `loadChildren: () => NgModule` so it applies to child routes with priority. The `_injector`
|
|
2562
|
+
// is created from the static providers on that parent route, so it applies to the children as
|
|
2563
|
+
// well, but only if there is no lazy loaded NgModuleRef injector.
|
|
2564
|
+
if (route?._loadedInjector)
|
|
2565
|
+
return route._loadedInjector;
|
|
2566
|
+
if (route?._injector)
|
|
2567
|
+
return route._injector;
|
|
2568
|
+
}
|
|
2569
|
+
return null;
|
|
2570
|
+
}
|
|
2571
|
+
|
|
2572
|
+
/**
|
|
2573
|
+
* @license
|
|
2574
|
+
* Copyright Google LLC All Rights Reserved.
|
|
2575
|
+
*
|
|
2576
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
2577
|
+
* found in the LICENSE file at https://angular.io/license
|
|
2578
|
+
*/
|
|
2579
|
+
const activateRoutes = (rootContexts, routeReuseStrategy, forwardEvent) => map(t => {
|
|
2580
|
+
new ActivateRoutes(routeReuseStrategy, t.targetRouterState, t.currentRouterState, forwardEvent)
|
|
2581
|
+
.activate(rootContexts);
|
|
2582
|
+
return t;
|
|
2583
|
+
});
|
|
2584
|
+
class ActivateRoutes {
|
|
2585
|
+
constructor(routeReuseStrategy, futureState, currState, forwardEvent) {
|
|
2586
|
+
this.routeReuseStrategy = routeReuseStrategy;
|
|
2587
|
+
this.futureState = futureState;
|
|
2588
|
+
this.currState = currState;
|
|
2589
|
+
this.forwardEvent = forwardEvent;
|
|
2590
|
+
}
|
|
2591
|
+
activate(parentContexts) {
|
|
2592
|
+
const futureRoot = this.futureState._root;
|
|
2593
|
+
const currRoot = this.currState ? this.currState._root : null;
|
|
2594
|
+
this.deactivateChildRoutes(futureRoot, currRoot, parentContexts);
|
|
2595
|
+
advanceActivatedRoute(this.futureState.root);
|
|
2596
|
+
this.activateChildRoutes(futureRoot, currRoot, parentContexts);
|
|
2597
|
+
}
|
|
2598
|
+
// De-activate the child route that are not re-used for the future state
|
|
2599
|
+
deactivateChildRoutes(futureNode, currNode, contexts) {
|
|
2600
|
+
const children = nodeChildrenAsMap(currNode);
|
|
2601
|
+
// Recurse on the routes active in the future state to de-activate deeper children
|
|
2602
|
+
futureNode.children.forEach(futureChild => {
|
|
2603
|
+
const childOutletName = futureChild.value.outlet;
|
|
2604
|
+
this.deactivateRoutes(futureChild, children[childOutletName], contexts);
|
|
2605
|
+
delete children[childOutletName];
|
|
2606
|
+
});
|
|
2607
|
+
// De-activate the routes that will not be re-used
|
|
2608
|
+
forEach(children, (v, childName) => {
|
|
2609
|
+
this.deactivateRouteAndItsChildren(v, contexts);
|
|
2610
|
+
});
|
|
2611
|
+
}
|
|
2612
|
+
deactivateRoutes(futureNode, currNode, parentContext) {
|
|
2613
|
+
const future = futureNode.value;
|
|
2614
|
+
const curr = currNode ? currNode.value : null;
|
|
2615
|
+
if (future === curr) {
|
|
2616
|
+
// Reusing the node, check to see if the children need to be de-activated
|
|
2617
|
+
if (future.component) {
|
|
2618
|
+
// If we have a normal route, we need to go through an outlet.
|
|
2619
|
+
const context = parentContext.getContext(future.outlet);
|
|
2620
|
+
if (context) {
|
|
2621
|
+
this.deactivateChildRoutes(futureNode, currNode, context.children);
|
|
2622
|
+
}
|
|
2623
|
+
}
|
|
2624
|
+
else {
|
|
2625
|
+
// if we have a componentless route, we recurse but keep the same outlet map.
|
|
2626
|
+
this.deactivateChildRoutes(futureNode, currNode, parentContext);
|
|
2627
|
+
}
|
|
2628
|
+
}
|
|
2629
|
+
else {
|
|
2630
|
+
if (curr) {
|
|
2631
|
+
// Deactivate the current route which will not be re-used
|
|
2632
|
+
this.deactivateRouteAndItsChildren(currNode, parentContext);
|
|
2633
|
+
}
|
|
2634
|
+
}
|
|
2635
|
+
}
|
|
2636
|
+
deactivateRouteAndItsChildren(route, parentContexts) {
|
|
2637
|
+
// If there is no component, the Route is never attached to an outlet (because there is no
|
|
2638
|
+
// component to attach).
|
|
2639
|
+
if (route.value.component && this.routeReuseStrategy.shouldDetach(route.value.snapshot)) {
|
|
2640
|
+
this.detachAndStoreRouteSubtree(route, parentContexts);
|
|
2641
|
+
}
|
|
2642
|
+
else {
|
|
2643
|
+
this.deactivateRouteAndOutlet(route, parentContexts);
|
|
2644
|
+
}
|
|
2645
|
+
}
|
|
2646
|
+
detachAndStoreRouteSubtree(route, parentContexts) {
|
|
2647
|
+
const context = parentContexts.getContext(route.value.outlet);
|
|
2648
|
+
const contexts = context && route.value.component ? context.children : parentContexts;
|
|
2649
|
+
const children = nodeChildrenAsMap(route);
|
|
2650
|
+
for (const childOutlet of Object.keys(children)) {
|
|
2651
|
+
this.deactivateRouteAndItsChildren(children[childOutlet], contexts);
|
|
2652
|
+
}
|
|
2653
|
+
if (context && context.outlet) {
|
|
2654
|
+
const componentRef = context.outlet.detach();
|
|
2655
|
+
const contexts = context.children.onOutletDeactivated();
|
|
2656
|
+
this.routeReuseStrategy.store(route.value.snapshot, { componentRef, route, contexts });
|
|
2657
|
+
}
|
|
2658
|
+
}
|
|
2659
|
+
deactivateRouteAndOutlet(route, parentContexts) {
|
|
2660
|
+
const context = parentContexts.getContext(route.value.outlet);
|
|
2661
|
+
// The context could be `null` if we are on a componentless route but there may still be
|
|
2662
|
+
// children that need deactivating.
|
|
2663
|
+
const contexts = context && route.value.component ? context.children : parentContexts;
|
|
2664
|
+
const children = nodeChildrenAsMap(route);
|
|
2665
|
+
for (const childOutlet of Object.keys(children)) {
|
|
2666
|
+
this.deactivateRouteAndItsChildren(children[childOutlet], contexts);
|
|
2667
|
+
}
|
|
2668
|
+
if (context && context.outlet) {
|
|
2669
|
+
// Destroy the component
|
|
2670
|
+
context.outlet.deactivate();
|
|
2671
|
+
// Destroy the contexts for all the outlets that were in the component
|
|
2672
|
+
context.children.onOutletDeactivated();
|
|
2673
|
+
// Clear the information about the attached component on the context but keep the reference to
|
|
2674
|
+
// the outlet.
|
|
2675
|
+
context.attachRef = null;
|
|
2676
|
+
context.resolver = null;
|
|
2677
|
+
context.route = null;
|
|
2678
|
+
}
|
|
2679
|
+
}
|
|
2680
|
+
activateChildRoutes(futureNode, currNode, contexts) {
|
|
2681
|
+
const children = nodeChildrenAsMap(currNode);
|
|
2682
|
+
futureNode.children.forEach(c => {
|
|
2683
|
+
this.activateRoutes(c, children[c.value.outlet], contexts);
|
|
2684
|
+
this.forwardEvent(new ActivationEnd(c.value.snapshot));
|
|
2685
|
+
});
|
|
2686
|
+
if (futureNode.children.length) {
|
|
2687
|
+
this.forwardEvent(new ChildActivationEnd(futureNode.value.snapshot));
|
|
2688
|
+
}
|
|
2689
|
+
}
|
|
2690
|
+
activateRoutes(futureNode, currNode, parentContexts) {
|
|
2691
|
+
const future = futureNode.value;
|
|
2692
|
+
const curr = currNode ? currNode.value : null;
|
|
2693
|
+
advanceActivatedRoute(future);
|
|
2694
|
+
// reusing the node
|
|
2695
|
+
if (future === curr) {
|
|
2696
|
+
if (future.component) {
|
|
2697
|
+
// If we have a normal route, we need to go through an outlet.
|
|
2698
|
+
const context = parentContexts.getOrCreateContext(future.outlet);
|
|
2699
|
+
this.activateChildRoutes(futureNode, currNode, context.children);
|
|
2700
|
+
}
|
|
2701
|
+
else {
|
|
2702
|
+
// if we have a componentless route, we recurse but keep the same outlet map.
|
|
2703
|
+
this.activateChildRoutes(futureNode, currNode, parentContexts);
|
|
2704
|
+
}
|
|
2705
|
+
}
|
|
2706
|
+
else {
|
|
2707
|
+
if (future.component) {
|
|
2708
|
+
// if we have a normal route, we need to place the component into the outlet and recurse.
|
|
2709
|
+
const context = parentContexts.getOrCreateContext(future.outlet);
|
|
2710
|
+
if (this.routeReuseStrategy.shouldAttach(future.snapshot)) {
|
|
2711
|
+
const stored = this.routeReuseStrategy.retrieve(future.snapshot);
|
|
2712
|
+
this.routeReuseStrategy.store(future.snapshot, null);
|
|
2713
|
+
context.children.onOutletReAttached(stored.contexts);
|
|
2714
|
+
context.attachRef = stored.componentRef;
|
|
2715
|
+
context.route = stored.route.value;
|
|
2716
|
+
if (context.outlet) {
|
|
2717
|
+
// Attach right away when the outlet has already been instantiated
|
|
2718
|
+
// Otherwise attach from `RouterOutlet.ngOnInit` when it is instantiated
|
|
2719
|
+
context.outlet.attach(stored.componentRef, stored.route.value);
|
|
2720
|
+
}
|
|
2721
|
+
advanceActivatedRoute(stored.route.value);
|
|
2722
|
+
this.activateChildRoutes(futureNode, null, context.children);
|
|
2723
|
+
}
|
|
2724
|
+
else {
|
|
2725
|
+
const injector = getClosestRouteInjector(future.snapshot);
|
|
2726
|
+
const cmpFactoryResolver = injector?.get(ComponentFactoryResolver) ?? null;
|
|
2727
|
+
context.attachRef = null;
|
|
2728
|
+
context.route = future;
|
|
2729
|
+
context.resolver = cmpFactoryResolver;
|
|
2730
|
+
context.injector = injector;
|
|
2731
|
+
if (context.outlet) {
|
|
2732
|
+
// Activate the outlet when it has already been instantiated
|
|
2733
|
+
// Otherwise it will get activated from its `ngOnInit` when instantiated
|
|
2734
|
+
context.outlet.activateWith(future, context.injector);
|
|
2735
|
+
}
|
|
2736
|
+
this.activateChildRoutes(futureNode, null, context.children);
|
|
2737
|
+
}
|
|
2738
|
+
}
|
|
2739
|
+
else {
|
|
2740
|
+
// if we have a componentless route, we recurse but keep the same outlet map.
|
|
2741
|
+
this.activateChildRoutes(futureNode, null, parentContexts);
|
|
2742
|
+
}
|
|
2743
|
+
}
|
|
2564
2744
|
}
|
|
2565
2745
|
}
|
|
2566
2746
|
|
|
@@ -2572,22 +2752,39 @@ class OutletInjector {
|
|
|
2572
2752
|
* found in the LICENSE file at https://angular.io/license
|
|
2573
2753
|
*/
|
|
2574
2754
|
/**
|
|
2575
|
-
*
|
|
2576
|
-
* router-outlet is needed. For example, with a config such as:
|
|
2755
|
+
* Simple function check, but generic so type inference will flow. Example:
|
|
2577
2756
|
*
|
|
2578
|
-
*
|
|
2757
|
+
* function product(a: number, b: number) {
|
|
2758
|
+
* return a * b;
|
|
2759
|
+
* }
|
|
2579
2760
|
*
|
|
2580
|
-
*
|
|
2581
|
-
*
|
|
2761
|
+
* if (isFunction<product>(fn)) {
|
|
2762
|
+
* return fn(1, 2);
|
|
2763
|
+
* } else {
|
|
2764
|
+
* throw "Must provide the `product` function";
|
|
2765
|
+
* }
|
|
2582
2766
|
*/
|
|
2583
|
-
|
|
2767
|
+
function isFunction(v) {
|
|
2768
|
+
return typeof v === 'function';
|
|
2769
|
+
}
|
|
2770
|
+
function isBoolean(v) {
|
|
2771
|
+
return typeof v === 'boolean';
|
|
2772
|
+
}
|
|
2773
|
+
function isUrlTree(v) {
|
|
2774
|
+
return v instanceof UrlTree;
|
|
2775
|
+
}
|
|
2776
|
+
function isCanLoad(guard) {
|
|
2777
|
+
return guard && isFunction(guard.canLoad);
|
|
2778
|
+
}
|
|
2779
|
+
function isCanActivate(guard) {
|
|
2780
|
+
return guard && isFunction(guard.canActivate);
|
|
2781
|
+
}
|
|
2782
|
+
function isCanActivateChild(guard) {
|
|
2783
|
+
return guard && isFunction(guard.canActivateChild);
|
|
2784
|
+
}
|
|
2785
|
+
function isCanDeactivate(guard) {
|
|
2786
|
+
return guard && isFunction(guard.canDeactivate);
|
|
2584
2787
|
}
|
|
2585
|
-
ɵEmptyOutletComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: ɵEmptyOutletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2586
|
-
ɵ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"] }] });
|
|
2587
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: ɵEmptyOutletComponent, decorators: [{
|
|
2588
|
-
type: Component,
|
|
2589
|
-
args: [{ template: `<router-outlet></router-outlet>` }]
|
|
2590
|
-
}] });
|
|
2591
2788
|
|
|
2592
2789
|
/**
|
|
2593
2790
|
* @license
|
|
@@ -2596,113 +2793,36 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9",
|
|
|
2596
2793
|
* Use of this source code is governed by an MIT-style license that can be
|
|
2597
2794
|
* found in the LICENSE file at https://angular.io/license
|
|
2598
2795
|
*/
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
if (route.redirectTo && route.children) {
|
|
2630
|
-
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and children cannot be used together`);
|
|
2631
|
-
}
|
|
2632
|
-
if (route.redirectTo && route.loadChildren) {
|
|
2633
|
-
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and loadChildren cannot be used together`);
|
|
2634
|
-
}
|
|
2635
|
-
if (route.children && route.loadChildren) {
|
|
2636
|
-
throw new Error(`Invalid configuration of route '${fullPath}': children and loadChildren cannot be used together`);
|
|
2637
|
-
}
|
|
2638
|
-
if (route.redirectTo && route.component) {
|
|
2639
|
-
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and component cannot be used together`);
|
|
2640
|
-
}
|
|
2641
|
-
if (route.redirectTo && route.canActivate) {
|
|
2642
|
-
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and canActivate cannot be used together. Redirects happen before activation ` +
|
|
2643
|
-
`so canActivate will never be executed.`);
|
|
2644
|
-
}
|
|
2645
|
-
if (route.path && route.matcher) {
|
|
2646
|
-
throw new Error(`Invalid configuration of route '${fullPath}': path and matcher cannot be used together`);
|
|
2647
|
-
}
|
|
2648
|
-
if (route.redirectTo === void 0 && !route.component && !route.children && !route.loadChildren) {
|
|
2649
|
-
throw new Error(`Invalid configuration of route '${fullPath}'. One of the following must be provided: component, redirectTo, children or loadChildren`);
|
|
2650
|
-
}
|
|
2651
|
-
if (route.path === void 0 && route.matcher === void 0) {
|
|
2652
|
-
throw new Error(`Invalid configuration of route '${fullPath}': routes must have either a path or a matcher specified`);
|
|
2653
|
-
}
|
|
2654
|
-
if (typeof route.path === 'string' && route.path.charAt(0) === '/') {
|
|
2655
|
-
throw new Error(`Invalid configuration of route '${fullPath}': path cannot start with a slash`);
|
|
2656
|
-
}
|
|
2657
|
-
if (route.path === '' && route.redirectTo !== void 0 && route.pathMatch === void 0) {
|
|
2658
|
-
const exp = `The default value of 'pathMatch' is 'prefix', but often the intent is to use 'full'.`;
|
|
2659
|
-
throw new Error(`Invalid configuration of route '{path: "${fullPath}", redirectTo: "${route.redirectTo}"}': please provide 'pathMatch'. ${exp}`);
|
|
2660
|
-
}
|
|
2661
|
-
}
|
|
2662
|
-
if (route.children) {
|
|
2663
|
-
validateConfig(route.children, fullPath);
|
|
2664
|
-
}
|
|
2665
|
-
}
|
|
2666
|
-
function getFullPath(parentPath, currentRoute) {
|
|
2667
|
-
if (!currentRoute) {
|
|
2668
|
-
return parentPath;
|
|
2669
|
-
}
|
|
2670
|
-
if (!parentPath && !currentRoute.path) {
|
|
2671
|
-
return '';
|
|
2672
|
-
}
|
|
2673
|
-
else if (parentPath && !currentRoute.path) {
|
|
2674
|
-
return `${parentPath}/`;
|
|
2675
|
-
}
|
|
2676
|
-
else if (!parentPath && currentRoute.path) {
|
|
2677
|
-
return currentRoute.path;
|
|
2678
|
-
}
|
|
2679
|
-
else {
|
|
2680
|
-
return `${parentPath}/${currentRoute.path}`;
|
|
2681
|
-
}
|
|
2682
|
-
}
|
|
2683
|
-
/**
|
|
2684
|
-
* Makes a copy of the config and adds any default required properties.
|
|
2685
|
-
*/
|
|
2686
|
-
function standardizeConfig(r) {
|
|
2687
|
-
const children = r.children && r.children.map(standardizeConfig);
|
|
2688
|
-
const c = children ? { ...r, children } : { ...r };
|
|
2689
|
-
if (!c.component && (children || c.loadChildren) && (c.outlet && c.outlet !== PRIMARY_OUTLET)) {
|
|
2690
|
-
c.component = ɵEmptyOutletComponent;
|
|
2691
|
-
}
|
|
2692
|
-
return c;
|
|
2693
|
-
}
|
|
2694
|
-
/** Returns the `route.outlet` or PRIMARY_OUTLET if none exists. */
|
|
2695
|
-
function getOutlet(route) {
|
|
2696
|
-
return route.outlet || PRIMARY_OUTLET;
|
|
2697
|
-
}
|
|
2698
|
-
/**
|
|
2699
|
-
* Sorts the `routes` such that the ones with an outlet matching `outletName` come first.
|
|
2700
|
-
* The order of the configs is otherwise preserved.
|
|
2701
|
-
*/
|
|
2702
|
-
function sortByMatchingOutlets(routes, outletName) {
|
|
2703
|
-
const sortedConfig = routes.filter(r => getOutlet(r) === outletName);
|
|
2704
|
-
sortedConfig.push(...routes.filter(r => getOutlet(r) !== outletName));
|
|
2705
|
-
return sortedConfig;
|
|
2796
|
+
const INITIAL_VALUE = Symbol('INITIAL_VALUE');
|
|
2797
|
+
function prioritizedGuardValue() {
|
|
2798
|
+
return switchMap(obs => {
|
|
2799
|
+
return combineLatest(obs.map(o => o.pipe(take(1), startWith(INITIAL_VALUE))))
|
|
2800
|
+
.pipe(scan((acc, list) => {
|
|
2801
|
+
let isPending = false;
|
|
2802
|
+
return list.reduce((innerAcc, val, i) => {
|
|
2803
|
+
if (innerAcc !== INITIAL_VALUE)
|
|
2804
|
+
return innerAcc;
|
|
2805
|
+
// Toggle pending flag if any values haven't been set yet
|
|
2806
|
+
if (val === INITIAL_VALUE)
|
|
2807
|
+
isPending = true;
|
|
2808
|
+
// Any other return values are only valid if we haven't yet hit a pending
|
|
2809
|
+
// call. This guarantees that in the case of a guard at the bottom of the
|
|
2810
|
+
// tree that returns a redirect, we will wait for the higher priority
|
|
2811
|
+
// guard at the top to finish before performing the redirect.
|
|
2812
|
+
if (!isPending) {
|
|
2813
|
+
// Early return when we hit a `false` value as that should always
|
|
2814
|
+
// cancel navigation
|
|
2815
|
+
if (val === false)
|
|
2816
|
+
return val;
|
|
2817
|
+
if (i === list.length - 1 || isUrlTree(val)) {
|
|
2818
|
+
return val;
|
|
2819
|
+
}
|
|
2820
|
+
}
|
|
2821
|
+
return innerAcc;
|
|
2822
|
+
}, acc);
|
|
2823
|
+
}, INITIAL_VALUE), filter(item => item !== INITIAL_VALUE), map(item => isUrlTree(item) ? item : item === true), //
|
|
2824
|
+
take(1));
|
|
2825
|
+
});
|
|
2706
2826
|
}
|
|
2707
2827
|
|
|
2708
2828
|
/**
|
|
@@ -2780,6 +2900,9 @@ function addEmptyPathsToChildrenIfNeeded(segmentGroup, consumedSegments, slicedS
|
|
|
2780
2900
|
s._sourceSegment = segmentGroup;
|
|
2781
2901
|
if (relativeLinkResolution === 'legacy') {
|
|
2782
2902
|
s._segmentIndexShift = segmentGroup.segments.length;
|
|
2903
|
+
if (typeof ngDevMode === 'undefined' || !!ngDevMode) {
|
|
2904
|
+
s._segmentIndexShiftCorrected = consumedSegments.length;
|
|
2905
|
+
}
|
|
2783
2906
|
}
|
|
2784
2907
|
else {
|
|
2785
2908
|
s._segmentIndexShift = consumedSegments.length;
|
|
@@ -2880,17 +3003,17 @@ function canLoadFails(route) {
|
|
|
2880
3003
|
*
|
|
2881
3004
|
* Lazy modules are loaded along the way.
|
|
2882
3005
|
*/
|
|
2883
|
-
function applyRedirects$1(
|
|
2884
|
-
return new ApplyRedirects(
|
|
3006
|
+
function applyRedirects$1(injector, configLoader, urlSerializer, urlTree, config) {
|
|
3007
|
+
return new ApplyRedirects(injector, configLoader, urlSerializer, urlTree, config).apply();
|
|
2885
3008
|
}
|
|
2886
3009
|
class ApplyRedirects {
|
|
2887
|
-
constructor(
|
|
3010
|
+
constructor(injector, configLoader, urlSerializer, urlTree, config) {
|
|
3011
|
+
this.injector = injector;
|
|
2888
3012
|
this.configLoader = configLoader;
|
|
2889
3013
|
this.urlSerializer = urlSerializer;
|
|
2890
3014
|
this.urlTree = urlTree;
|
|
2891
3015
|
this.config = config;
|
|
2892
3016
|
this.allowRedirects = true;
|
|
2893
|
-
this.ngModule = moduleInjector.get(NgModuleRef);
|
|
2894
3017
|
}
|
|
2895
3018
|
apply() {
|
|
2896
3019
|
const splitGroup = split(this.urlTree.root, [], [], this.config).segmentGroup;
|
|
@@ -2901,7 +3024,7 @@ class ApplyRedirects {
|
|
|
2901
3024
|
// them. We should be able to remove this logic as a "breaking change" but should do some more
|
|
2902
3025
|
// investigation into the failures first.
|
|
2903
3026
|
const rootSegmentGroup = new UrlSegmentGroup(splitGroup.segments, splitGroup.children);
|
|
2904
|
-
const expanded$ = this.expandSegmentGroup(this.
|
|
3027
|
+
const expanded$ = this.expandSegmentGroup(this.injector, this.config, rootSegmentGroup, PRIMARY_OUTLET);
|
|
2905
3028
|
const urlTrees$ = expanded$.pipe(map((rootSegmentGroup) => {
|
|
2906
3029
|
return this.createUrlTree(squashSegmentGroup(rootSegmentGroup), this.urlTree.queryParams, this.urlTree.fragment);
|
|
2907
3030
|
}));
|
|
@@ -2920,7 +3043,7 @@ class ApplyRedirects {
|
|
|
2920
3043
|
}));
|
|
2921
3044
|
}
|
|
2922
3045
|
match(tree) {
|
|
2923
|
-
const expanded$ = this.expandSegmentGroup(this.
|
|
3046
|
+
const expanded$ = this.expandSegmentGroup(this.injector, this.config, tree.root, PRIMARY_OUTLET);
|
|
2924
3047
|
const mapped$ = expanded$.pipe(map((rootSegmentGroup) => {
|
|
2925
3048
|
return this.createUrlTree(squashSegmentGroup(rootSegmentGroup), tree.queryParams, tree.fragment);
|
|
2926
3049
|
}));
|
|
@@ -2940,15 +3063,15 @@ class ApplyRedirects {
|
|
|
2940
3063
|
rootCandidate;
|
|
2941
3064
|
return new UrlTree(root, queryParams, fragment);
|
|
2942
3065
|
}
|
|
2943
|
-
expandSegmentGroup(
|
|
3066
|
+
expandSegmentGroup(injector, routes, segmentGroup, outlet) {
|
|
2944
3067
|
if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) {
|
|
2945
|
-
return this.expandChildren(
|
|
3068
|
+
return this.expandChildren(injector, routes, segmentGroup)
|
|
2946
3069
|
.pipe(map((children) => new UrlSegmentGroup([], children)));
|
|
2947
3070
|
}
|
|
2948
|
-
return this.expandSegment(
|
|
3071
|
+
return this.expandSegment(injector, segmentGroup, routes, segmentGroup.segments, outlet, true);
|
|
2949
3072
|
}
|
|
2950
3073
|
// Recursively expand segment groups for all the child outlets
|
|
2951
|
-
expandChildren(
|
|
3074
|
+
expandChildren(injector, routes, segmentGroup) {
|
|
2952
3075
|
// Expand outlets one at a time, starting with the primary outlet. We need to do it this way
|
|
2953
3076
|
// because an absolute redirect from the primary outlet takes precedence.
|
|
2954
3077
|
const childOutlets = [];
|
|
@@ -2967,16 +3090,25 @@ class ApplyRedirects {
|
|
|
2967
3090
|
// first, followed by routes for other outlets, which might match if they have an
|
|
2968
3091
|
// empty path.
|
|
2969
3092
|
const sortedRoutes = sortByMatchingOutlets(routes, childOutlet);
|
|
2970
|
-
return this.expandSegmentGroup(
|
|
3093
|
+
return this.expandSegmentGroup(injector, sortedRoutes, child, childOutlet)
|
|
2971
3094
|
.pipe(map(s => ({ segment: s, outlet: childOutlet })));
|
|
2972
3095
|
}), scan((children, expandedChild) => {
|
|
2973
3096
|
children[expandedChild.outlet] = expandedChild.segment;
|
|
2974
3097
|
return children;
|
|
2975
3098
|
}, {}), last$1());
|
|
2976
3099
|
}
|
|
2977
|
-
expandSegment(
|
|
2978
|
-
return from(routes).pipe(concatMap(
|
|
2979
|
-
|
|
3100
|
+
expandSegment(injector, segmentGroup, routes, segments, outlet, allowRedirects) {
|
|
3101
|
+
return from(routes).pipe(concatMap(r => {
|
|
3102
|
+
if (r.providers && !r._injector) {
|
|
3103
|
+
r._injector = createEnvironmentInjector(r.providers, injector, `Route: ${r.path}`);
|
|
3104
|
+
}
|
|
3105
|
+
// We specifically _do not_ want to include the _loadedInjector here. The loaded injector
|
|
3106
|
+
// only applies to the route's children, not the route itself. Note that this distinction
|
|
3107
|
+
// only applies here to any tokens we try to retrieve during this phase. At the moment,
|
|
3108
|
+
// that only includes `canLoad`, which won't run again once the child module is loaded. As
|
|
3109
|
+
// a result, this makes no difference right now, but could in the future if there are more
|
|
3110
|
+
// actions here that need DI (for example, a canMatch guard).
|
|
3111
|
+
const expanded$ = this.expandSegmentAgainstRoute(r._injector ?? injector, segmentGroup, routes, r, segments, outlet, allowRedirects);
|
|
2980
3112
|
return expanded$.pipe(catchError((e) => {
|
|
2981
3113
|
if (e instanceof NoMatch$1) {
|
|
2982
3114
|
return of(null);
|
|
@@ -2993,35 +3125,35 @@ class ApplyRedirects {
|
|
|
2993
3125
|
throw e;
|
|
2994
3126
|
}));
|
|
2995
3127
|
}
|
|
2996
|
-
expandSegmentAgainstRoute(
|
|
3128
|
+
expandSegmentAgainstRoute(injector, segmentGroup, routes, route, paths, outlet, allowRedirects) {
|
|
2997
3129
|
if (!isImmediateMatch(route, segmentGroup, paths, outlet)) {
|
|
2998
3130
|
return noMatch(segmentGroup);
|
|
2999
3131
|
}
|
|
3000
3132
|
if (route.redirectTo === undefined) {
|
|
3001
|
-
return this.matchSegmentAgainstRoute(
|
|
3133
|
+
return this.matchSegmentAgainstRoute(injector, segmentGroup, route, paths, outlet);
|
|
3002
3134
|
}
|
|
3003
3135
|
if (allowRedirects && this.allowRedirects) {
|
|
3004
|
-
return this.expandSegmentAgainstRouteUsingRedirect(
|
|
3136
|
+
return this.expandSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, paths, outlet);
|
|
3005
3137
|
}
|
|
3006
3138
|
return noMatch(segmentGroup);
|
|
3007
3139
|
}
|
|
3008
|
-
expandSegmentAgainstRouteUsingRedirect(
|
|
3140
|
+
expandSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet) {
|
|
3009
3141
|
if (route.path === '**') {
|
|
3010
|
-
return this.expandWildCardWithParamsAgainstRouteUsingRedirect(
|
|
3142
|
+
return this.expandWildCardWithParamsAgainstRouteUsingRedirect(injector, routes, route, outlet);
|
|
3011
3143
|
}
|
|
3012
|
-
return this.expandRegularSegmentAgainstRouteUsingRedirect(
|
|
3144
|
+
return this.expandRegularSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet);
|
|
3013
3145
|
}
|
|
3014
|
-
expandWildCardWithParamsAgainstRouteUsingRedirect(
|
|
3146
|
+
expandWildCardWithParamsAgainstRouteUsingRedirect(injector, routes, route, outlet) {
|
|
3015
3147
|
const newTree = this.applyRedirectCommands([], route.redirectTo, {});
|
|
3016
3148
|
if (route.redirectTo.startsWith('/')) {
|
|
3017
3149
|
return absoluteRedirect(newTree);
|
|
3018
3150
|
}
|
|
3019
3151
|
return this.lineralizeSegments(route, newTree).pipe(mergeMap((newSegments) => {
|
|
3020
3152
|
const group = new UrlSegmentGroup(newSegments, {});
|
|
3021
|
-
return this.expandSegment(
|
|
3153
|
+
return this.expandSegment(injector, group, routes, newSegments, outlet, false);
|
|
3022
3154
|
}));
|
|
3023
3155
|
}
|
|
3024
|
-
expandRegularSegmentAgainstRouteUsingRedirect(
|
|
3156
|
+
expandRegularSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet) {
|
|
3025
3157
|
const { matched, consumedSegments, remainingSegments, positionalParamSegments } = match(segmentGroup, route, segments);
|
|
3026
3158
|
if (!matched)
|
|
3027
3159
|
return noMatch(segmentGroup);
|
|
@@ -3030,16 +3162,18 @@ class ApplyRedirects {
|
|
|
3030
3162
|
return absoluteRedirect(newTree);
|
|
3031
3163
|
}
|
|
3032
3164
|
return this.lineralizeSegments(route, newTree).pipe(mergeMap((newSegments) => {
|
|
3033
|
-
return this.expandSegment(
|
|
3165
|
+
return this.expandSegment(injector, segmentGroup, routes, newSegments.concat(remainingSegments), outlet, false);
|
|
3034
3166
|
}));
|
|
3035
3167
|
}
|
|
3036
|
-
matchSegmentAgainstRoute(
|
|
3168
|
+
matchSegmentAgainstRoute(injector, rawSegmentGroup, route, segments, outlet) {
|
|
3037
3169
|
if (route.path === '**') {
|
|
3038
3170
|
if (route.loadChildren) {
|
|
3039
|
-
const loaded$ = route.
|
|
3040
|
-
|
|
3171
|
+
const loaded$ = route._loadedRoutes ?
|
|
3172
|
+
of({ routes: route._loadedRoutes, injector: route._loadedInjector }) :
|
|
3173
|
+
this.configLoader.loadChildren(injector, route);
|
|
3041
3174
|
return loaded$.pipe(map((cfg) => {
|
|
3042
|
-
route.
|
|
3175
|
+
route._loadedRoutes = cfg.routes;
|
|
3176
|
+
route._loadedInjector = cfg.injector;
|
|
3043
3177
|
return new UrlSegmentGroup(segments, {});
|
|
3044
3178
|
}));
|
|
3045
3179
|
}
|
|
@@ -3048,55 +3182,55 @@ class ApplyRedirects {
|
|
|
3048
3182
|
const { matched, consumedSegments, remainingSegments } = match(rawSegmentGroup, route, segments);
|
|
3049
3183
|
if (!matched)
|
|
3050
3184
|
return noMatch(rawSegmentGroup);
|
|
3051
|
-
const childConfig$ = this.getChildConfig(
|
|
3185
|
+
const childConfig$ = this.getChildConfig(injector, route, segments);
|
|
3052
3186
|
return childConfig$.pipe(mergeMap((routerConfig) => {
|
|
3053
|
-
const
|
|
3187
|
+
const childInjector = routerConfig.injector ?? injector;
|
|
3054
3188
|
const childConfig = routerConfig.routes;
|
|
3055
3189
|
const { segmentGroup: splitSegmentGroup, slicedSegments } = split(rawSegmentGroup, consumedSegments, remainingSegments, childConfig);
|
|
3056
3190
|
// See comment on the other call to `split` about why this is necessary.
|
|
3057
3191
|
const segmentGroup = new UrlSegmentGroup(splitSegmentGroup.segments, splitSegmentGroup.children);
|
|
3058
3192
|
if (slicedSegments.length === 0 && segmentGroup.hasChildren()) {
|
|
3059
|
-
const expanded$ = this.expandChildren(
|
|
3193
|
+
const expanded$ = this.expandChildren(childInjector, childConfig, segmentGroup);
|
|
3060
3194
|
return expanded$.pipe(map((children) => new UrlSegmentGroup(consumedSegments, children)));
|
|
3061
3195
|
}
|
|
3062
3196
|
if (childConfig.length === 0 && slicedSegments.length === 0) {
|
|
3063
3197
|
return of(new UrlSegmentGroup(consumedSegments, {}));
|
|
3064
3198
|
}
|
|
3065
3199
|
const matchedOnOutlet = getOutlet(route) === outlet;
|
|
3066
|
-
const expanded$ = this.expandSegment(
|
|
3200
|
+
const expanded$ = this.expandSegment(childInjector, segmentGroup, childConfig, slicedSegments, matchedOnOutlet ? PRIMARY_OUTLET : outlet, true);
|
|
3067
3201
|
return expanded$.pipe(map((cs) => new UrlSegmentGroup(consumedSegments.concat(cs.segments), cs.children)));
|
|
3068
3202
|
}));
|
|
3069
3203
|
}
|
|
3070
|
-
getChildConfig(
|
|
3204
|
+
getChildConfig(injector, route, segments) {
|
|
3071
3205
|
if (route.children) {
|
|
3072
3206
|
// The children belong to the same module
|
|
3073
|
-
return of(
|
|
3207
|
+
return of({ routes: route.children, injector });
|
|
3074
3208
|
}
|
|
3075
3209
|
if (route.loadChildren) {
|
|
3076
3210
|
// lazy children belong to the loaded module
|
|
3077
|
-
if (route.
|
|
3078
|
-
return of(route.
|
|
3211
|
+
if (route._loadedRoutes !== undefined) {
|
|
3212
|
+
return of({ routes: route._loadedRoutes, injector: route._loadedInjector });
|
|
3079
3213
|
}
|
|
3080
|
-
return this.runCanLoadGuards(
|
|
3214
|
+
return this.runCanLoadGuards(injector, route, segments)
|
|
3081
3215
|
.pipe(mergeMap((shouldLoadResult) => {
|
|
3082
3216
|
if (shouldLoadResult) {
|
|
3083
|
-
return this.configLoader.
|
|
3084
|
-
.pipe(
|
|
3085
|
-
route.
|
|
3086
|
-
|
|
3217
|
+
return this.configLoader.loadChildren(injector, route)
|
|
3218
|
+
.pipe(tap((cfg) => {
|
|
3219
|
+
route._loadedRoutes = cfg.routes;
|
|
3220
|
+
route._loadedInjector = cfg.injector;
|
|
3087
3221
|
}));
|
|
3088
3222
|
}
|
|
3089
3223
|
return canLoadFails(route);
|
|
3090
3224
|
}));
|
|
3091
3225
|
}
|
|
3092
|
-
return of(
|
|
3226
|
+
return of({ routes: [], injector });
|
|
3093
3227
|
}
|
|
3094
|
-
runCanLoadGuards(
|
|
3228
|
+
runCanLoadGuards(injector, route, segments) {
|
|
3095
3229
|
const canLoad = route.canLoad;
|
|
3096
3230
|
if (!canLoad || canLoad.length === 0)
|
|
3097
3231
|
return of(true);
|
|
3098
3232
|
const canLoadObservables = canLoad.map((injectionToken) => {
|
|
3099
|
-
const guard =
|
|
3233
|
+
const guard = injector.get(injectionToken);
|
|
3100
3234
|
let guardVal;
|
|
3101
3235
|
if (isCanLoad(guard)) {
|
|
3102
3236
|
guardVal = guard.canLoad(route, segments);
|
|
@@ -3224,8 +3358,8 @@ function squashSegmentGroup(segmentGroup) {
|
|
|
3224
3358
|
* Use of this source code is governed by an MIT-style license that can be
|
|
3225
3359
|
* found in the LICENSE file at https://angular.io/license
|
|
3226
3360
|
*/
|
|
3227
|
-
function applyRedirects(
|
|
3228
|
-
return switchMap(t => applyRedirects$1(
|
|
3361
|
+
function applyRedirects(environmentInjector, configLoader, urlSerializer, config) {
|
|
3362
|
+
return switchMap(t => applyRedirects$1(environmentInjector, configLoader, urlSerializer, t.extractedUrl, config)
|
|
3229
3363
|
.pipe(map(urlAfterRedirects => ({ ...t, urlAfterRedirects }))));
|
|
3230
3364
|
}
|
|
3231
3365
|
|
|
@@ -3259,21 +3393,11 @@ function getCanActivateChild(p) {
|
|
|
3259
3393
|
return null;
|
|
3260
3394
|
return { node: p, guards: canActivateChild };
|
|
3261
3395
|
}
|
|
3262
|
-
function getToken(token, snapshot,
|
|
3263
|
-
const
|
|
3264
|
-
const injector =
|
|
3396
|
+
function getToken(token, snapshot, fallbackInjector) {
|
|
3397
|
+
const routeInjector = getClosestRouteInjector(snapshot);
|
|
3398
|
+
const injector = routeInjector ?? fallbackInjector;
|
|
3265
3399
|
return injector.get(token);
|
|
3266
3400
|
}
|
|
3267
|
-
function getClosestLoadedConfig(snapshot) {
|
|
3268
|
-
if (!snapshot)
|
|
3269
|
-
return null;
|
|
3270
|
-
for (let s = snapshot.parent; s; s = s.parent) {
|
|
3271
|
-
const route = s.routeConfig;
|
|
3272
|
-
if (route && route._loadedConfig)
|
|
3273
|
-
return route._loadedConfig;
|
|
3274
|
-
}
|
|
3275
|
-
return null;
|
|
3276
|
-
}
|
|
3277
3401
|
function getChildRouteGuards(futureNode, currNode, contexts, futurePath, checks = {
|
|
3278
3402
|
canDeactivateChecks: [],
|
|
3279
3403
|
canActivateChecks: []
|
|
@@ -3517,6 +3641,7 @@ function runCanDeactivate(component, currARS, currRSS, futureRSS, moduleInjector
|
|
|
3517
3641
|
* Use of this source code is governed by an MIT-style license that can be
|
|
3518
3642
|
* found in the LICENSE file at https://angular.io/license
|
|
3519
3643
|
*/
|
|
3644
|
+
const NG_DEV_MODE$2 = typeof ngDevMode === 'undefined' || !!ngDevMode;
|
|
3520
3645
|
class NoMatch {
|
|
3521
3646
|
}
|
|
3522
3647
|
function newObservableError(e) {
|
|
@@ -3632,7 +3757,13 @@ class Recognizer {
|
|
|
3632
3757
|
let remainingSegments = [];
|
|
3633
3758
|
if (route.path === '**') {
|
|
3634
3759
|
const params = segments.length > 0 ? last(segments).parameters : {};
|
|
3635
|
-
|
|
3760
|
+
const pathIndexShift = getPathIndexShift(rawSegment) + segments.length;
|
|
3761
|
+
snapshot = new ActivatedRouteSnapshot(segments, params, Object.freeze({ ...this.urlTree.queryParams }), this.urlTree.fragment, getData(route), getOutlet(route), route.component ?? route._loadedComponent ?? null, route, getSourceSegmentGroup(rawSegment), pathIndexShift, getResolve(route),
|
|
3762
|
+
// NG_DEV_MODE is used to prevent the getCorrectedPathIndexShift function from affecting
|
|
3763
|
+
// production bundle size. This value is intended only to surface a warning to users
|
|
3764
|
+
// depending on `relativeLinkResolution: 'legacy'` in dev mode.
|
|
3765
|
+
(NG_DEV_MODE$2 ? getCorrectedPathIndexShift(rawSegment) + segments.length :
|
|
3766
|
+
pathIndexShift));
|
|
3636
3767
|
}
|
|
3637
3768
|
else {
|
|
3638
3769
|
const result = match(rawSegment, route, segments);
|
|
@@ -3641,7 +3772,9 @@ class Recognizer {
|
|
|
3641
3772
|
}
|
|
3642
3773
|
consumedSegments = result.consumedSegments;
|
|
3643
3774
|
remainingSegments = result.remainingSegments;
|
|
3644
|
-
|
|
3775
|
+
const pathIndexShift = getPathIndexShift(rawSegment) + consumedSegments.length;
|
|
3776
|
+
snapshot = new ActivatedRouteSnapshot(consumedSegments, result.parameters, Object.freeze({ ...this.urlTree.queryParams }), this.urlTree.fragment, getData(route), getOutlet(route), route.component ?? route._loadedComponent ?? null, route, getSourceSegmentGroup(rawSegment), pathIndexShift, getResolve(route), (NG_DEV_MODE$2 ? getCorrectedPathIndexShift(rawSegment) + consumedSegments.length :
|
|
3777
|
+
pathIndexShift));
|
|
3645
3778
|
}
|
|
3646
3779
|
const childConfig = getChildConfig(route);
|
|
3647
3780
|
const { segmentGroup, slicedSegments } = split(rawSegment, consumedSegments, remainingSegments,
|
|
@@ -3689,7 +3822,7 @@ function getChildConfig(route) {
|
|
|
3689
3822
|
return route.children;
|
|
3690
3823
|
}
|
|
3691
3824
|
if (route.loadChildren) {
|
|
3692
|
-
return route.
|
|
3825
|
+
return route._loadedRoutes;
|
|
3693
3826
|
}
|
|
3694
3827
|
return [];
|
|
3695
3828
|
}
|
|
@@ -3751,10 +3884,19 @@ function getSourceSegmentGroup(segmentGroup) {
|
|
|
3751
3884
|
}
|
|
3752
3885
|
function getPathIndexShift(segmentGroup) {
|
|
3753
3886
|
let s = segmentGroup;
|
|
3754
|
-
let res =
|
|
3887
|
+
let res = s._segmentIndexShift ?? 0;
|
|
3888
|
+
while (s._sourceSegment) {
|
|
3889
|
+
s = s._sourceSegment;
|
|
3890
|
+
res += s._segmentIndexShift ?? 0;
|
|
3891
|
+
}
|
|
3892
|
+
return res - 1;
|
|
3893
|
+
}
|
|
3894
|
+
function getCorrectedPathIndexShift(segmentGroup) {
|
|
3895
|
+
let s = segmentGroup;
|
|
3896
|
+
let res = s._segmentIndexShiftCorrected ?? s._segmentIndexShift ?? 0;
|
|
3755
3897
|
while (s._sourceSegment) {
|
|
3756
3898
|
s = s._sourceSegment;
|
|
3757
|
-
res +=
|
|
3899
|
+
res += s._segmentIndexShiftCorrected ?? s._segmentIndexShift ?? 0;
|
|
3758
3900
|
}
|
|
3759
3901
|
return res - 1;
|
|
3760
3902
|
}
|
|
@@ -3804,22 +3946,16 @@ function resolveData(paramsInheritanceStrategy, moduleInjector) {
|
|
|
3804
3946
|
function runResolve(futureARS, futureRSS, paramsInheritanceStrategy, moduleInjector) {
|
|
3805
3947
|
const config = futureARS.routeConfig;
|
|
3806
3948
|
const resolve = futureARS._resolve;
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
if (typeof config.title === 'string' || config.title === null) {
|
|
3810
|
-
data[RouteTitle] = config.title;
|
|
3811
|
-
}
|
|
3812
|
-
else {
|
|
3813
|
-
resolve[RouteTitle] = config.title;
|
|
3814
|
-
}
|
|
3949
|
+
if (config?.title !== undefined && !hasStaticTitle(config)) {
|
|
3950
|
+
resolve[RouteTitle] = config.title;
|
|
3815
3951
|
}
|
|
3816
3952
|
return resolveNode(resolve, futureARS, futureRSS, moduleInjector)
|
|
3817
3953
|
.pipe(map((resolvedData) => {
|
|
3818
3954
|
futureARS._resolvedData = resolvedData;
|
|
3819
|
-
futureARS.data =
|
|
3820
|
-
|
|
3821
|
-
|
|
3822
|
-
}
|
|
3955
|
+
futureARS.data = inheritedParamsDataResolve(futureARS, paramsInheritanceStrategy).resolve;
|
|
3956
|
+
if (config && hasStaticTitle(config)) {
|
|
3957
|
+
futureARS.data[RouteTitle] = config.title;
|
|
3958
|
+
}
|
|
3823
3959
|
return null;
|
|
3824
3960
|
}));
|
|
3825
3961
|
}
|
|
@@ -3830,16 +3966,9 @@ function resolveNode(resolve, futureARS, futureRSS, moduleInjector) {
|
|
|
3830
3966
|
}
|
|
3831
3967
|
const data = {};
|
|
3832
3968
|
return from(keys).pipe(mergeMap(key => getResolver(resolve[key], futureARS, futureRSS, moduleInjector)
|
|
3833
|
-
.pipe(
|
|
3969
|
+
.pipe(first(), tap((value) => {
|
|
3834
3970
|
data[key] = value;
|
|
3835
|
-
}))), takeLast(1),
|
|
3836
|
-
// Ensure all resolvers returned values, otherwise don't emit any "next" and just complete
|
|
3837
|
-
// the chain which will cancel navigation
|
|
3838
|
-
if (getDataKeys(data).length === keys.length) {
|
|
3839
|
-
return of(data);
|
|
3840
|
-
}
|
|
3841
|
-
return EMPTY;
|
|
3842
|
-
}));
|
|
3971
|
+
}))), takeLast(1), mapTo(data), catchError((e) => e instanceof EmptyError ? EMPTY : throwError(e)));
|
|
3843
3972
|
}
|
|
3844
3973
|
function getDataKeys(obj) {
|
|
3845
3974
|
return [...Object.keys(obj), ...Object.getOwnPropertySymbols(obj)];
|
|
@@ -3849,6 +3978,9 @@ function getResolver(injectionToken, futureARS, futureRSS, moduleInjector) {
|
|
|
3849
3978
|
return resolver.resolve ? wrapIntoObservable(resolver.resolve(futureARS, futureRSS)) :
|
|
3850
3979
|
wrapIntoObservable(resolver(futureARS, futureRSS));
|
|
3851
3980
|
}
|
|
3981
|
+
function hasStaticTitle(config) {
|
|
3982
|
+
return typeof config.title === 'string' || config.title === null;
|
|
3983
|
+
}
|
|
3852
3984
|
|
|
3853
3985
|
/**
|
|
3854
3986
|
* @license
|
|
@@ -3945,6 +4077,7 @@ class DefaultRouteReuseStrategy extends BaseRouteReuseStrategy {
|
|
|
3945
4077
|
* Use of this source code is governed by an MIT-style license that can be
|
|
3946
4078
|
* found in the LICENSE file at https://angular.io/license
|
|
3947
4079
|
*/
|
|
4080
|
+
const NG_DEV_MODE$1 = typeof ngDevMode === 'undefined' || !!ngDevMode;
|
|
3948
4081
|
/**
|
|
3949
4082
|
* The [DI token](guide/glossary/#di-token) for a router configuration.
|
|
3950
4083
|
*
|
|
@@ -3957,43 +4090,84 @@ class DefaultRouteReuseStrategy extends BaseRouteReuseStrategy {
|
|
|
3957
4090
|
*/
|
|
3958
4091
|
const ROUTES = new InjectionToken('ROUTES');
|
|
3959
4092
|
class RouterConfigLoader {
|
|
3960
|
-
constructor(injector, compiler
|
|
4093
|
+
constructor(injector, compiler) {
|
|
3961
4094
|
this.injector = injector;
|
|
3962
4095
|
this.compiler = compiler;
|
|
3963
|
-
this.
|
|
3964
|
-
this.
|
|
4096
|
+
this.componentLoaders = new WeakMap();
|
|
4097
|
+
this.childrenLoaders = new WeakMap();
|
|
4098
|
+
}
|
|
4099
|
+
loadComponent(route) {
|
|
4100
|
+
if (this.componentLoaders.get(route)) {
|
|
4101
|
+
return this.componentLoaders.get(route);
|
|
4102
|
+
}
|
|
4103
|
+
else if (route._loadedComponent) {
|
|
4104
|
+
return of(route._loadedComponent);
|
|
4105
|
+
}
|
|
4106
|
+
if (this.onLoadStartListener) {
|
|
4107
|
+
this.onLoadStartListener(route);
|
|
4108
|
+
}
|
|
4109
|
+
const loadRunner = wrapIntoObservable(route.loadComponent())
|
|
4110
|
+
.pipe(tap(component => {
|
|
4111
|
+
if (this.onLoadEndListener) {
|
|
4112
|
+
this.onLoadEndListener(route);
|
|
4113
|
+
}
|
|
4114
|
+
NG_DEV_MODE$1 && assertStandalone(route.path ?? '', component);
|
|
4115
|
+
route._loadedComponent = component;
|
|
4116
|
+
}), finalize(() => {
|
|
4117
|
+
this.componentLoaders.delete(route);
|
|
4118
|
+
}));
|
|
4119
|
+
// Use custom ConnectableObservable as share in runners pipe increasing the bundle size too much
|
|
4120
|
+
const loader = new ConnectableObservable(loadRunner, () => new Subject()).pipe(refCount());
|
|
4121
|
+
this.componentLoaders.set(route, loader);
|
|
4122
|
+
return loader;
|
|
3965
4123
|
}
|
|
3966
|
-
|
|
3967
|
-
if (route
|
|
3968
|
-
return route
|
|
4124
|
+
loadChildren(parentInjector, route) {
|
|
4125
|
+
if (this.childrenLoaders.get(route)) {
|
|
4126
|
+
return this.childrenLoaders.get(route);
|
|
4127
|
+
}
|
|
4128
|
+
else if (route._loadedRoutes) {
|
|
4129
|
+
return of({ routes: route._loadedRoutes, injector: route._loadedInjector });
|
|
3969
4130
|
}
|
|
3970
4131
|
if (this.onLoadStartListener) {
|
|
3971
4132
|
this.onLoadStartListener(route);
|
|
3972
4133
|
}
|
|
3973
|
-
const
|
|
3974
|
-
const loadRunner =
|
|
4134
|
+
const moduleFactoryOrRoutes$ = this.loadModuleFactoryOrRoutes(route.loadChildren);
|
|
4135
|
+
const loadRunner = moduleFactoryOrRoutes$.pipe(map((factoryOrRoutes) => {
|
|
3975
4136
|
if (this.onLoadEndListener) {
|
|
3976
4137
|
this.onLoadEndListener(route);
|
|
3977
4138
|
}
|
|
3978
|
-
|
|
3979
|
-
//
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
|
|
4139
|
+
// This injector comes from the `NgModuleRef` when lazy loading an `NgModule`. There is no
|
|
4140
|
+
// injector associated with lazy loading a `Route` array.
|
|
4141
|
+
let injector;
|
|
4142
|
+
let rawRoutes;
|
|
4143
|
+
let requireStandaloneComponents = false;
|
|
4144
|
+
if (Array.isArray(factoryOrRoutes)) {
|
|
4145
|
+
rawRoutes = factoryOrRoutes;
|
|
4146
|
+
requireStandaloneComponents = true;
|
|
4147
|
+
}
|
|
4148
|
+
else {
|
|
4149
|
+
injector = factoryOrRoutes.create(parentInjector).injector;
|
|
4150
|
+
// When loading a module that doesn't provide `RouterModule.forChild()` preloader
|
|
4151
|
+
// will get stuck in an infinite loop. The child module's Injector will look to
|
|
4152
|
+
// its parent `Injector` when it doesn't find any ROUTES so it will return routes
|
|
4153
|
+
// for it's parent module instead.
|
|
4154
|
+
rawRoutes = flatten(injector.get(ROUTES, [], InjectFlags.Self | InjectFlags.Optional));
|
|
4155
|
+
}
|
|
4156
|
+
const routes = rawRoutes.map(standardizeConfig);
|
|
4157
|
+
NG_DEV_MODE$1 && validateConfig(routes, route.path, requireStandaloneComponents);
|
|
4158
|
+
return { routes, injector };
|
|
4159
|
+
}), finalize(() => {
|
|
4160
|
+
this.childrenLoaders.delete(route);
|
|
3988
4161
|
}));
|
|
3989
4162
|
// Use custom ConnectableObservable as share in runners pipe increasing the bundle size too much
|
|
3990
|
-
|
|
4163
|
+
const loader = new ConnectableObservable(loadRunner, () => new Subject())
|
|
3991
4164
|
.pipe(refCount());
|
|
3992
|
-
|
|
4165
|
+
this.childrenLoaders.set(route, loader);
|
|
4166
|
+
return loader;
|
|
3993
4167
|
}
|
|
3994
|
-
|
|
4168
|
+
loadModuleFactoryOrRoutes(loadChildren) {
|
|
3995
4169
|
return wrapIntoObservable(loadChildren()).pipe(mergeMap((t) => {
|
|
3996
|
-
if (t instanceof NgModuleFactory) {
|
|
4170
|
+
if (t instanceof NgModuleFactory || Array.isArray(t)) {
|
|
3997
4171
|
return of(t);
|
|
3998
4172
|
}
|
|
3999
4173
|
else {
|
|
@@ -4002,6 +4176,11 @@ class RouterConfigLoader {
|
|
|
4002
4176
|
}));
|
|
4003
4177
|
}
|
|
4004
4178
|
}
|
|
4179
|
+
RouterConfigLoader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.0", ngImport: i0, type: RouterConfigLoader, deps: [{ token: i0.Injector }, { token: i0.Compiler }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
4180
|
+
RouterConfigLoader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-rc.0", ngImport: i0, type: RouterConfigLoader });
|
|
4181
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.0", ngImport: i0, type: RouterConfigLoader, decorators: [{
|
|
4182
|
+
type: Injectable
|
|
4183
|
+
}], ctorParameters: function () { return [{ type: i0.Injector }, { type: i0.Compiler }]; } });
|
|
4005
4184
|
|
|
4006
4185
|
/**
|
|
4007
4186
|
* @license
|
|
@@ -4041,6 +4220,7 @@ class DefaultUrlHandlingStrategy {
|
|
|
4041
4220
|
* Use of this source code is governed by an MIT-style license that can be
|
|
4042
4221
|
* found in the LICENSE file at https://angular.io/license
|
|
4043
4222
|
*/
|
|
4223
|
+
const NG_DEV_MODE = typeof ngDevMode === 'undefined' || !!ngDevMode;
|
|
4044
4224
|
function defaultErrorHandler(error) {
|
|
4045
4225
|
throw error;
|
|
4046
4226
|
}
|
|
@@ -4183,6 +4363,8 @@ class Router {
|
|
|
4183
4363
|
/**
|
|
4184
4364
|
* Enables a bug fix that corrects relative link resolution in components with empty paths.
|
|
4185
4365
|
* @see `RouterModule`
|
|
4366
|
+
*
|
|
4367
|
+
* @deprecated
|
|
4186
4368
|
*/
|
|
4187
4369
|
this.relativeLinkResolution = 'corrected';
|
|
4188
4370
|
/**
|
|
@@ -4210,6 +4392,9 @@ class Router {
|
|
|
4210
4392
|
this.canceledNavigationResolution = 'replace';
|
|
4211
4393
|
const onLoadStart = (r) => this.triggerEvent(new RouteConfigLoadStart(r));
|
|
4212
4394
|
const onLoadEnd = (r) => this.triggerEvent(new RouteConfigLoadEnd(r));
|
|
4395
|
+
this.configLoader = injector.get(RouterConfigLoader);
|
|
4396
|
+
this.configLoader.onLoadEndListener = onLoadEnd;
|
|
4397
|
+
this.configLoader.onLoadStartListener = onLoadStart;
|
|
4213
4398
|
this.ngModule = injector.get(NgModuleRef);
|
|
4214
4399
|
this.console = injector.get(ɵConsole);
|
|
4215
4400
|
const ngZone = injector.get(NgZone);
|
|
@@ -4218,7 +4403,6 @@ class Router {
|
|
|
4218
4403
|
this.currentUrlTree = createEmptyUrlTree();
|
|
4219
4404
|
this.rawUrlTree = this.currentUrlTree;
|
|
4220
4405
|
this.browserUrlTree = this.currentUrlTree;
|
|
4221
|
-
this.configLoader = new RouterConfigLoader(injector, compiler, onLoadStart, onLoadEnd);
|
|
4222
4406
|
this.routerState = createEmptyState(this.currentUrlTree, this.rootComponentType);
|
|
4223
4407
|
this.transitions = new BehaviorSubject({
|
|
4224
4408
|
id: 0,
|
|
@@ -4427,6 +4611,25 @@ class Router {
|
|
|
4427
4611
|
skipLocationChange: !!skipLocationChange,
|
|
4428
4612
|
replaceUrl: !!replaceUrl,
|
|
4429
4613
|
});
|
|
4614
|
+
}),
|
|
4615
|
+
// --- LOAD COMPONENTS ---
|
|
4616
|
+
switchTap((t) => {
|
|
4617
|
+
const loadComponents = (route) => {
|
|
4618
|
+
const loaders = [];
|
|
4619
|
+
if (route.routeConfig?.loadComponent &&
|
|
4620
|
+
!route.routeConfig._loadedComponent) {
|
|
4621
|
+
loaders.push(this.configLoader.loadComponent(route.routeConfig)
|
|
4622
|
+
.pipe(tap(loadedComponent => {
|
|
4623
|
+
route.component = loadedComponent;
|
|
4624
|
+
}), map(() => void 0)));
|
|
4625
|
+
}
|
|
4626
|
+
for (const child of route.children) {
|
|
4627
|
+
loaders.push(...loadComponents(child));
|
|
4628
|
+
}
|
|
4629
|
+
return loaders;
|
|
4630
|
+
};
|
|
4631
|
+
return combineLatest(loadComponents(t.targetSnapshot.root))
|
|
4632
|
+
.pipe(defaultIfEmpty(), take(1));
|
|
4430
4633
|
}), map((t) => {
|
|
4431
4634
|
const targetRouterState = createRouterState(this.routeReuseStrategy, t.targetSnapshot, t.currentRouterState);
|
|
4432
4635
|
return ({ ...t, targetRouterState });
|
|
@@ -4505,23 +4708,17 @@ class Router {
|
|
|
4505
4708
|
t.resolve(false);
|
|
4506
4709
|
}
|
|
4507
4710
|
else {
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
|
|
4515
|
-
|
|
4516
|
-
|
|
4517
|
-
|
|
4518
|
-
|
|
4519
|
-
// the navigation is rejected.
|
|
4520
|
-
replaceUrl: this.urlUpdateStrategy === 'eager' ||
|
|
4521
|
-
isBrowserTriggeredNavigation(t.source)
|
|
4522
|
-
};
|
|
4523
|
-
this.scheduleNavigation(mergedTree, 'imperative', null, extras, { resolve: t.resolve, reject: t.reject, promise: t.promise });
|
|
4524
|
-
}, 0);
|
|
4711
|
+
const mergedTree = this.urlHandlingStrategy.merge(e.url, this.rawUrlTree);
|
|
4712
|
+
const extras = {
|
|
4713
|
+
skipLocationChange: t.extras.skipLocationChange,
|
|
4714
|
+
// The URL is already updated at this point if we have 'eager' URL
|
|
4715
|
+
// updates or if the navigation was triggered by the browser (back
|
|
4716
|
+
// button, URL bar, etc). We want to replace that item in history if
|
|
4717
|
+
// the navigation is rejected.
|
|
4718
|
+
replaceUrl: this.urlUpdateStrategy === 'eager' ||
|
|
4719
|
+
isBrowserTriggeredNavigation(t.source)
|
|
4720
|
+
};
|
|
4721
|
+
this.scheduleNavigation(mergedTree, 'imperative', null, extras, { resolve: t.resolve, reject: t.reject, promise: t.promise });
|
|
4525
4722
|
}
|
|
4526
4723
|
/* All other errors should reset to the router's internal URL reference to
|
|
4527
4724
|
* the pre-error state. */
|
|
@@ -4631,7 +4828,7 @@ class Router {
|
|
|
4631
4828
|
* ```
|
|
4632
4829
|
*/
|
|
4633
4830
|
resetConfig(config) {
|
|
4634
|
-
validateConfig(config);
|
|
4831
|
+
NG_DEV_MODE && validateConfig(config);
|
|
4635
4832
|
this.config = config.map(standardizeConfig);
|
|
4636
4833
|
this.navigated = false;
|
|
4637
4834
|
this.lastSuccessfulId = -1;
|
|
@@ -4986,9 +5183,9 @@ class Router {
|
|
|
4986
5183
|
return { navigationId };
|
|
4987
5184
|
}
|
|
4988
5185
|
}
|
|
4989
|
-
Router.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-
|
|
4990
|
-
Router.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-
|
|
4991
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-
|
|
5186
|
+
Router.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.0", ngImport: i0, type: Router, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
|
|
5187
|
+
Router.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-rc.0", ngImport: i0, type: Router });
|
|
5188
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.0", ngImport: i0, type: Router, decorators: [{
|
|
4992
5189
|
type: Injectable
|
|
4993
5190
|
}], ctorParameters: function () { return [{ type: i0.Type }, { type: UrlSerializer }, { type: ChildrenOutletContexts }, { type: i3.Location }, { type: i0.Injector }, { type: i0.Compiler }, { type: undefined }]; } });
|
|
4994
5191
|
function validateCommands(commands) {
|
|
@@ -5187,9 +5384,9 @@ class RouterLink {
|
|
|
5187
5384
|
});
|
|
5188
5385
|
}
|
|
5189
5386
|
}
|
|
5190
|
-
RouterLink.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-
|
|
5191
|
-
RouterLink.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "
|
|
5192
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-
|
|
5387
|
+
RouterLink.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.0", ngImport: i0, type: RouterLink, deps: [{ token: Router }, { token: ActivatedRoute }, { token: 'tabindex', attribute: true }, { token: i0.Renderer2 }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
|
|
5388
|
+
RouterLink.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.0.0-rc.0", 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 });
|
|
5389
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.0", ngImport: i0, type: RouterLink, decorators: [{
|
|
5193
5390
|
type: Directive,
|
|
5194
5391
|
args: [{ selector: ':not(a):not(area)[routerLink]' }]
|
|
5195
5392
|
}], ctorParameters: function () { return [{ type: Router }, { type: ActivatedRoute }, { type: undefined, decorators: [{
|
|
@@ -5306,9 +5503,9 @@ class RouterLinkWithHref {
|
|
|
5306
5503
|
});
|
|
5307
5504
|
}
|
|
5308
5505
|
}
|
|
5309
|
-
RouterLinkWithHref.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-
|
|
5310
|
-
RouterLinkWithHref.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "
|
|
5311
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-
|
|
5506
|
+
RouterLinkWithHref.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.0", ngImport: i0, type: RouterLinkWithHref, deps: [{ token: Router }, { token: ActivatedRoute }, { token: i3.LocationStrategy }], target: i0.ɵɵFactoryTarget.Directive });
|
|
5507
|
+
RouterLinkWithHref.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.0.0-rc.0", 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 });
|
|
5508
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.0", ngImport: i0, type: RouterLinkWithHref, decorators: [{
|
|
5312
5509
|
type: Directive,
|
|
5313
5510
|
args: [{ selector: 'a[routerLink],area[routerLink]' }]
|
|
5314
5511
|
}], ctorParameters: function () { return [{ type: Router }, { type: ActivatedRoute }, { type: i3.LocationStrategy }]; }, propDecorators: { target: [{
|
|
@@ -5405,6 +5602,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9",
|
|
|
5405
5602
|
* </div>
|
|
5406
5603
|
* ```
|
|
5407
5604
|
*
|
|
5605
|
+
* The `RouterLinkActive` directive can also be used to set the aria-current attribute
|
|
5606
|
+
* to provide an alternative distinction for active elements to visually impaired users.
|
|
5607
|
+
*
|
|
5608
|
+
* For example, the following code adds the 'active' class to the Home Page link when it is
|
|
5609
|
+
* indeed active and in such case also sets its aria-current attribute to 'page':
|
|
5610
|
+
*
|
|
5611
|
+
* ```
|
|
5612
|
+
* <a routerLink="/" routerLinkActive="active" ariaCurrentWhenActive="page">Home Page</a>
|
|
5613
|
+
* ```
|
|
5614
|
+
*
|
|
5408
5615
|
* @ngModule RouterModule
|
|
5409
5616
|
*
|
|
5410
5617
|
* @publicApi
|
|
@@ -5498,6 +5705,12 @@ class RouterLinkActive {
|
|
|
5498
5705
|
this.renderer.removeClass(this.element.nativeElement, c);
|
|
5499
5706
|
}
|
|
5500
5707
|
});
|
|
5708
|
+
if (hasActiveLinks && this.ariaCurrentWhenActive !== undefined) {
|
|
5709
|
+
this.renderer.setAttribute(this.element.nativeElement, 'aria-current', this.ariaCurrentWhenActive.toString());
|
|
5710
|
+
}
|
|
5711
|
+
else {
|
|
5712
|
+
this.renderer.removeAttribute(this.element.nativeElement, 'aria-current');
|
|
5713
|
+
}
|
|
5501
5714
|
// Emit on isActiveChange after classes are updated
|
|
5502
5715
|
this.isActiveChange.emit(hasActiveLinks);
|
|
5503
5716
|
}
|
|
@@ -5517,9 +5730,9 @@ class RouterLinkActive {
|
|
|
5517
5730
|
this.links.some(isActiveCheckFn) || this.linksWithHrefs.some(isActiveCheckFn);
|
|
5518
5731
|
}
|
|
5519
5732
|
}
|
|
5520
|
-
RouterLinkActive.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-
|
|
5521
|
-
RouterLinkActive.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "
|
|
5522
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-
|
|
5733
|
+
RouterLinkActive.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.0", 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 });
|
|
5734
|
+
RouterLinkActive.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.0.0-rc.0", 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 });
|
|
5735
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.0", ngImport: i0, type: RouterLinkActive, decorators: [{
|
|
5523
5736
|
type: Directive,
|
|
5524
5737
|
args: [{
|
|
5525
5738
|
selector: '[routerLinkActive]',
|
|
@@ -5537,6 +5750,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9",
|
|
|
5537
5750
|
args: [RouterLinkWithHref, { descendants: true }]
|
|
5538
5751
|
}], routerLinkActiveOptions: [{
|
|
5539
5752
|
type: Input
|
|
5753
|
+
}], ariaCurrentWhenActive: [{
|
|
5754
|
+
type: Input
|
|
5540
5755
|
}], isActiveChange: [{
|
|
5541
5756
|
type: Output
|
|
5542
5757
|
}], routerLinkActive: [{
|
|
@@ -5620,9 +5835,9 @@ class DefaultTitleStrategy extends TitleStrategy {
|
|
|
5620
5835
|
}
|
|
5621
5836
|
}
|
|
5622
5837
|
}
|
|
5623
|
-
DefaultTitleStrategy.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-
|
|
5624
|
-
DefaultTitleStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-
|
|
5625
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-
|
|
5838
|
+
DefaultTitleStrategy.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.0", ngImport: i0, type: DefaultTitleStrategy, deps: [{ token: i1.Title }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
5839
|
+
DefaultTitleStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-rc.0", ngImport: i0, type: DefaultTitleStrategy, providedIn: 'root' });
|
|
5840
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.0", ngImport: i0, type: DefaultTitleStrategy, decorators: [{
|
|
5626
5841
|
type: Injectable,
|
|
5627
5842
|
args: [{ providedIn: 'root' }]
|
|
5628
5843
|
}], ctorParameters: function () { return [{ type: i1.Title }]; } });
|
|
@@ -5686,13 +5901,11 @@ class NoPreloading {
|
|
|
5686
5901
|
* @publicApi
|
|
5687
5902
|
*/
|
|
5688
5903
|
class RouterPreloader {
|
|
5689
|
-
constructor(router, compiler, injector, preloadingStrategy) {
|
|
5904
|
+
constructor(router, compiler, injector, preloadingStrategy, loader) {
|
|
5690
5905
|
this.router = router;
|
|
5691
5906
|
this.injector = injector;
|
|
5692
5907
|
this.preloadingStrategy = preloadingStrategy;
|
|
5693
|
-
|
|
5694
|
-
const onEndLoad = (r) => router.triggerEvent(new RouteConfigLoadEnd(r));
|
|
5695
|
-
this.loader = new RouterConfigLoader(injector, compiler, onStartLoad, onEndLoad);
|
|
5908
|
+
this.loader = loader;
|
|
5696
5909
|
}
|
|
5697
5910
|
setUpPreloading() {
|
|
5698
5911
|
this.subscription =
|
|
@@ -5701,8 +5914,7 @@ class RouterPreloader {
|
|
|
5701
5914
|
.subscribe(() => { });
|
|
5702
5915
|
}
|
|
5703
5916
|
preload() {
|
|
5704
|
-
|
|
5705
|
-
return this.processRoutes(ngModule, this.router.config);
|
|
5917
|
+
return this.processRoutes(this.injector, this.router.config);
|
|
5706
5918
|
}
|
|
5707
5919
|
/** @nodoc */
|
|
5708
5920
|
ngOnDestroy() {
|
|
@@ -5710,41 +5922,59 @@ class RouterPreloader {
|
|
|
5710
5922
|
this.subscription.unsubscribe();
|
|
5711
5923
|
}
|
|
5712
5924
|
}
|
|
5713
|
-
processRoutes(
|
|
5925
|
+
processRoutes(injector, routes) {
|
|
5714
5926
|
const res = [];
|
|
5715
5927
|
for (const route of routes) {
|
|
5716
|
-
|
|
5717
|
-
|
|
5718
|
-
|
|
5719
|
-
res.push(this.processRoutes(childConfig.module, childConfig.routes));
|
|
5720
|
-
// no config loaded, fetch the config
|
|
5928
|
+
if (route.providers && !route._injector) {
|
|
5929
|
+
route._injector =
|
|
5930
|
+
createEnvironmentInjector(route.providers, injector, `Route: ${route.path}`);
|
|
5721
5931
|
}
|
|
5722
|
-
|
|
5723
|
-
|
|
5724
|
-
|
|
5932
|
+
const injectorForCurrentRoute = route._injector ?? injector;
|
|
5933
|
+
const injectorForChildren = route._loadedInjector ?? injectorForCurrentRoute;
|
|
5934
|
+
if ((route.loadChildren && !route._loadedRoutes) ||
|
|
5935
|
+
(route.loadComponent && !route._loadedComponent)) {
|
|
5936
|
+
res.push(this.preloadConfig(injectorForCurrentRoute, route));
|
|
5725
5937
|
}
|
|
5726
|
-
else if (route.children) {
|
|
5727
|
-
res.push(this.processRoutes(
|
|
5938
|
+
else if (route.children || route._loadedRoutes) {
|
|
5939
|
+
res.push(this.processRoutes(injectorForChildren, (route.children ?? route._loadedRoutes)));
|
|
5728
5940
|
}
|
|
5729
5941
|
}
|
|
5730
|
-
return from(res).pipe(mergeAll()
|
|
5942
|
+
return from(res).pipe(mergeAll());
|
|
5731
5943
|
}
|
|
5732
|
-
preloadConfig(
|
|
5944
|
+
preloadConfig(injector, route) {
|
|
5733
5945
|
return this.preloadingStrategy.preload(route, () => {
|
|
5734
|
-
|
|
5735
|
-
|
|
5736
|
-
|
|
5737
|
-
|
|
5738
|
-
|
|
5946
|
+
let loadedChildren$;
|
|
5947
|
+
if (route.loadChildren && route.canLoad === undefined) {
|
|
5948
|
+
loadedChildren$ = this.loader.loadChildren(injector, route);
|
|
5949
|
+
}
|
|
5950
|
+
else {
|
|
5951
|
+
loadedChildren$ = of(null);
|
|
5952
|
+
}
|
|
5953
|
+
const recursiveLoadChildren$ = loadedChildren$.pipe(mergeMap((config) => {
|
|
5954
|
+
if (config === null) {
|
|
5955
|
+
return of(void 0);
|
|
5956
|
+
}
|
|
5957
|
+
route._loadedRoutes = config.routes;
|
|
5958
|
+
route._loadedInjector = config.injector;
|
|
5959
|
+
// If the loaded config was a module, use that as the module/module injector going
|
|
5960
|
+
// forward. Otherwise, continue using the current module/module injector.
|
|
5961
|
+
return this.processRoutes(config.injector ?? injector, config.routes);
|
|
5739
5962
|
}));
|
|
5963
|
+
if (route.loadComponent && !route._loadedComponent) {
|
|
5964
|
+
const loadComponent$ = this.loader.loadComponent(route);
|
|
5965
|
+
return from([recursiveLoadChildren$, loadComponent$]).pipe(mergeAll());
|
|
5966
|
+
}
|
|
5967
|
+
else {
|
|
5968
|
+
return recursiveLoadChildren$;
|
|
5969
|
+
}
|
|
5740
5970
|
});
|
|
5741
5971
|
}
|
|
5742
5972
|
}
|
|
5743
|
-
RouterPreloader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-
|
|
5744
|
-
RouterPreloader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-
|
|
5745
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-
|
|
5973
|
+
RouterPreloader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.0", ngImport: i0, type: RouterPreloader, deps: [{ token: Router }, { token: i0.Compiler }, { token: i0.EnvironmentInjector }, { token: PreloadingStrategy }, { token: RouterConfigLoader }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
5974
|
+
RouterPreloader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-rc.0", ngImport: i0, type: RouterPreloader });
|
|
5975
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.0", ngImport: i0, type: RouterPreloader, decorators: [{
|
|
5746
5976
|
type: Injectable
|
|
5747
|
-
}], ctorParameters: function () { return [{ type: Router }, { type: i0.Compiler }, { type: i0.
|
|
5977
|
+
}], ctorParameters: function () { return [{ type: Router }, { type: i0.Compiler }, { type: i0.EnvironmentInjector }, { type: PreloadingStrategy }, { type: RouterConfigLoader }]; } });
|
|
5748
5978
|
|
|
5749
5979
|
/**
|
|
5750
5980
|
* @license
|
|
@@ -5828,9 +6058,9 @@ class RouterScroller {
|
|
|
5828
6058
|
}
|
|
5829
6059
|
}
|
|
5830
6060
|
}
|
|
5831
|
-
RouterScroller.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-
|
|
5832
|
-
RouterScroller.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-
|
|
5833
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-
|
|
6061
|
+
RouterScroller.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.0", ngImport: i0, type: RouterScroller, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
|
|
6062
|
+
RouterScroller.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-rc.0", ngImport: i0, type: RouterScroller });
|
|
6063
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.0", ngImport: i0, type: RouterScroller, decorators: [{
|
|
5834
6064
|
type: Injectable
|
|
5835
6065
|
}], ctorParameters: function () { return [{ type: Router }, { type: i3.ViewportScroller }, { type: undefined }]; } });
|
|
5836
6066
|
|
|
@@ -5873,6 +6103,7 @@ const ROUTER_PROVIDERS = [
|
|
|
5873
6103
|
NoPreloading,
|
|
5874
6104
|
PreloadAllModules,
|
|
5875
6105
|
{ provide: ROUTER_CONFIGURATION, useValue: { enableTracing: false } },
|
|
6106
|
+
RouterConfigLoader,
|
|
5876
6107
|
];
|
|
5877
6108
|
function routerNgProbeToken() {
|
|
5878
6109
|
return new NgProbeToken('Router', Router);
|
|
@@ -5971,10 +6202,10 @@ class RouterModule {
|
|
|
5971
6202
|
return { ngModule: RouterModule, providers: [provideRoutes(routes)] };
|
|
5972
6203
|
}
|
|
5973
6204
|
}
|
|
5974
|
-
RouterModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-
|
|
5975
|
-
RouterModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "
|
|
5976
|
-
RouterModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.0-
|
|
5977
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-
|
|
6205
|
+
RouterModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.0", ngImport: i0, type: RouterModule, deps: [{ token: ROUTER_FORROOT_GUARD, optional: true }, { token: Router, optional: true }], target: i0.ɵɵFactoryTarget.NgModule });
|
|
6206
|
+
RouterModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.0.0-rc.0", ngImport: i0, type: RouterModule, declarations: [RouterOutlet, RouterLink, RouterLinkWithHref, RouterLinkActive, ɵEmptyOutletComponent], exports: [RouterOutlet, RouterLink, RouterLinkWithHref, RouterLinkActive, ɵEmptyOutletComponent] });
|
|
6207
|
+
RouterModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.0-rc.0", ngImport: i0, type: RouterModule });
|
|
6208
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.0", ngImport: i0, type: RouterModule, decorators: [{
|
|
5978
6209
|
type: NgModule,
|
|
5979
6210
|
args: [{
|
|
5980
6211
|
declarations: ROUTER_DIRECTIVES,
|
|
@@ -6036,11 +6267,11 @@ function setupRouter(urlSerializer, contexts, location, injector, compiler, conf
|
|
|
6036
6267
|
}
|
|
6037
6268
|
router.titleStrategy = titleStrategy ?? defaultTitleStrategy;
|
|
6038
6269
|
assignExtraOptionsToRouter(opts, router);
|
|
6039
|
-
if (opts.enableTracing) {
|
|
6270
|
+
if ((typeof ngDevMode === 'undefined' || ngDevMode) && opts.enableTracing) {
|
|
6040
6271
|
router.events.subscribe((e) => {
|
|
6041
6272
|
// tslint:disable:no-console
|
|
6042
6273
|
console.group?.(`Router Event: ${e.constructor.name}`);
|
|
6043
|
-
console.log(e
|
|
6274
|
+
console.log(stringifyEvent(e));
|
|
6044
6275
|
console.log(e);
|
|
6045
6276
|
console.groupEnd?.();
|
|
6046
6277
|
// tslint:enable:no-console
|
|
@@ -6107,9 +6338,7 @@ class RouterInitializer {
|
|
|
6107
6338
|
router.setUpLocationChangeListener();
|
|
6108
6339
|
resolve(true);
|
|
6109
6340
|
}
|
|
6110
|
-
else if (
|
|
6111
|
-
// TODO: enabled is deprecated as of v11, can be removed in v13
|
|
6112
|
-
opts.initialNavigation === 'enabled' || opts.initialNavigation === 'enabledBlocking') {
|
|
6341
|
+
else if (opts.initialNavigation === 'enabledBlocking') {
|
|
6113
6342
|
router.hooks.afterPreactivation = () => {
|
|
6114
6343
|
// only the initial navigation should be delayed
|
|
6115
6344
|
if (!this.initNavigation) {
|
|
@@ -6153,9 +6382,9 @@ class RouterInitializer {
|
|
|
6153
6382
|
this.destroyed = true;
|
|
6154
6383
|
}
|
|
6155
6384
|
}
|
|
6156
|
-
RouterInitializer.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-
|
|
6157
|
-
RouterInitializer.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-
|
|
6158
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-
|
|
6385
|
+
RouterInitializer.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.0", ngImport: i0, type: RouterInitializer, deps: [{ token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
6386
|
+
RouterInitializer.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-rc.0", ngImport: i0, type: RouterInitializer });
|
|
6387
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.0", ngImport: i0, type: RouterInitializer, decorators: [{
|
|
6159
6388
|
type: Injectable
|
|
6160
6389
|
}], ctorParameters: function () { return [{ type: i0.Injector }]; } });
|
|
6161
6390
|
function getAppInitializer(r) {
|
|
@@ -6195,7 +6424,7 @@ function provideRouterInitializer() {
|
|
|
6195
6424
|
/**
|
|
6196
6425
|
* @publicApi
|
|
6197
6426
|
*/
|
|
6198
|
-
const VERSION = new Version('14.0.0-
|
|
6427
|
+
const VERSION = new Version('14.0.0-rc.0');
|
|
6199
6428
|
|
|
6200
6429
|
/**
|
|
6201
6430
|
* @license
|