@angular/router 14.0.0-next.9 → 14.0.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2020/src/apply_redirects.mjs +52 -48
- package/esm2020/src/components/empty_outlet.mjs +3 -3
- package/esm2020/src/create_url_tree.mjs +25 -11
- package/esm2020/src/directives/router_link.mjs +6 -6
- package/esm2020/src/directives/router_link_active.mjs +22 -4
- package/esm2020/src/directives/router_outlet.mjs +25 -16
- package/esm2020/src/events.mjs +57 -1
- package/esm2020/src/index.mjs +1 -1
- package/esm2020/src/models.mjs +2 -7
- package/esm2020/src/operators/activate_routes.mjs +7 -14
- package/esm2020/src/operators/apply_redirects.mjs +3 -3
- package/esm2020/src/operators/resolve_data.mjs +14 -24
- package/esm2020/src/page_title_strategy.mjs +3 -3
- package/esm2020/src/recognize.mjs +24 -6
- package/esm2020/src/router.mjs +43 -25
- package/esm2020/src/router_config_loader.mjs +74 -27
- package/esm2020/src/router_module.mjs +14 -14
- package/esm2020/src/router_outlet_context.mjs +6 -1
- package/esm2020/src/router_preloader.mjs +48 -32
- package/esm2020/src/router_scroller.mjs +3 -3
- package/esm2020/src/router_state.mjs +4 -4
- package/esm2020/src/url_tree.mjs +1 -1
- package/esm2020/src/utils/config.mjs +86 -11
- package/esm2020/src/utils/config_matching.mjs +4 -1
- package/esm2020/src/utils/preactivation.mjs +5 -14
- package/esm2020/src/version.mjs +1 -1
- package/esm2020/testing/src/router_testing_module.mjs +4 -4
- package/fesm2015/router.mjs +927 -670
- package/fesm2015/router.mjs.map +1 -1
- package/fesm2015/testing.mjs +5 -5
- package/fesm2015/upgrade.mjs +1 -1
- package/fesm2020/router.mjs +912 -673
- package/fesm2020/router.mjs.map +1 -1
- package/fesm2020/testing.mjs +5 -5
- package/fesm2020/upgrade.mjs +1 -1
- package/{router.d.ts → index.d.ts} +3858 -3730
- package/package.json +9 -9
- package/testing/{testing.d.ts → index.d.ts} +65 -64
- package/upgrade/{upgrade.d.ts → index.d.ts} +51 -50
- package/testing/package.json +0 -9
- package/upgrade/package.json +0 -10
package/fesm2020/router.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular v14.0.0-
|
|
2
|
+
* @license Angular v14.0.0-rc.2
|
|
3
3
|
* (c) 2010-2022 Google LLC. https://angular.io/
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
@@ -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, createEnvironmentInjector, ɵisStandalone, ComponentFactoryResolver, InjectionToken, InjectFlags, NgModuleFactory, Injectable, NgModuleRef, ɵConsole, NgZone, ɵcoerceToBoolean, Input, HostListener, HostBinding, Optional, ContentChildren, Injector, Compiler, NgProbeToken, ANALYZE_FOR_ENTRY_COMPONENTS, SkipSelf, Inject, APP_INITIALIZER, APP_BOOTSTRAP_LISTENER, NgModule, ApplicationRef, Version } from '@angular/core';
|
|
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.2", ngImport: i0, type: RouterOutlet, deps: [{ token: ChildrenOutletContexts }, { token: i0.ViewContainerRef }, { token: 'name', attribute: true }, { token: i0.ChangeDetectorRef }, { token: i0.EnvironmentInjector }], target: i0.ɵɵFactoryTarget.Directive });
|
|
2332
|
+
RouterOutlet.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.0.0-rc.2", type: RouterOutlet, selector: "router-outlet", outputs: { activateEvents: "activate", deactivateEvents: "deactivate", attachEvents: "attach", detachEvents: "detach" }, exportAs: ["outlet"], ngImport: i0 });
|
|
2333
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.2", 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,400 @@ 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.2", ngImport: i0, type: ɵEmptyOutletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2391
|
+
ɵEmptyOutletComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.0-rc.2", type: ɵEmptyOutletComponent, selector: "ng-component", ngImport: i0, template: `<router-outlet></router-outlet>`, isInline: true, dependencies: [{ kind: "directive", type: RouterOutlet, selector: "router-outlet", outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }] });
|
|
2392
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.2", 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
|
+
/**
|
|
2405
|
+
* Creates an `EnvironmentInjector` if the `Route` has providers and one does not already exist
|
|
2406
|
+
* and returns the injector. Otherwise, if the `Route` does not have `providers`, returns the
|
|
2407
|
+
* `currentInjector`.
|
|
2408
|
+
*
|
|
2409
|
+
* @param route The route that might have providers
|
|
2410
|
+
* @param currentInjector The parent injector of the `Route`
|
|
2411
|
+
*/
|
|
2412
|
+
function getOrCreateRouteInjectorIfNeeded(route, currentInjector) {
|
|
2413
|
+
if (route.providers && !route._injector) {
|
|
2414
|
+
route._injector =
|
|
2415
|
+
createEnvironmentInjector(route.providers, currentInjector, `Route: ${route.path}`);
|
|
2416
|
+
}
|
|
2417
|
+
return route._injector ?? currentInjector;
|
|
2418
|
+
}
|
|
2419
|
+
function getLoadedRoutes(route) {
|
|
2420
|
+
return route._loadedRoutes;
|
|
2421
|
+
}
|
|
2422
|
+
function getLoadedInjector(route) {
|
|
2423
|
+
return route._loadedInjector;
|
|
2424
|
+
}
|
|
2425
|
+
function getLoadedComponent(route) {
|
|
2426
|
+
return route._loadedComponent;
|
|
2427
|
+
}
|
|
2428
|
+
function getProvidersInjector(route) {
|
|
2429
|
+
return route._injector;
|
|
2430
|
+
}
|
|
2431
|
+
function validateConfig(config, parentPath = '', requireStandaloneComponents = false) {
|
|
2432
|
+
// forEach doesn't iterate undefined values
|
|
2433
|
+
for (let i = 0; i < config.length; i++) {
|
|
2434
|
+
const route = config[i];
|
|
2435
|
+
const fullPath = getFullPath(parentPath, route);
|
|
2436
|
+
validateNode(route, fullPath, requireStandaloneComponents);
|
|
2437
|
+
}
|
|
2438
|
+
}
|
|
2439
|
+
function assertStandalone(fullPath, component) {
|
|
2440
|
+
if (component && !ɵisStandalone(component)) {
|
|
2441
|
+
throw new Error(`Invalid configuration of route '${fullPath}'. The component must be standalone.`);
|
|
2442
|
+
}
|
|
2443
|
+
}
|
|
2444
|
+
function validateNode(route, fullPath, requireStandaloneComponents) {
|
|
2445
|
+
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
2446
|
+
if (!route) {
|
|
2447
|
+
throw new Error(`
|
|
2448
|
+
Invalid configuration of route '${fullPath}': Encountered undefined route.
|
|
2449
|
+
The reason might be an extra comma.
|
|
2450
|
+
|
|
2451
|
+
Example:
|
|
2452
|
+
const routes: Routes = [
|
|
2453
|
+
{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },
|
|
2454
|
+
{ path: 'dashboard', component: DashboardComponent },, << two commas
|
|
2455
|
+
{ path: 'detail/:id', component: HeroDetailComponent }
|
|
2456
|
+
];
|
|
2457
|
+
`);
|
|
2458
|
+
}
|
|
2459
|
+
if (Array.isArray(route)) {
|
|
2460
|
+
throw new Error(`Invalid configuration of route '${fullPath}': Array cannot be specified`);
|
|
2461
|
+
}
|
|
2462
|
+
if (!route.component && !route.loadComponent && !route.children && !route.loadChildren &&
|
|
2463
|
+
(route.outlet && route.outlet !== PRIMARY_OUTLET)) {
|
|
2464
|
+
throw new Error(`Invalid configuration of route '${fullPath}': a componentless route without children or loadChildren cannot have a named outlet set`);
|
|
2465
|
+
}
|
|
2466
|
+
if (route.redirectTo && route.children) {
|
|
2467
|
+
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and children cannot be used together`);
|
|
2468
|
+
}
|
|
2469
|
+
if (route.redirectTo && route.loadChildren) {
|
|
2470
|
+
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and loadChildren cannot be used together`);
|
|
2471
|
+
}
|
|
2472
|
+
if (route.children && route.loadChildren) {
|
|
2473
|
+
throw new Error(`Invalid configuration of route '${fullPath}': children and loadChildren cannot be used together`);
|
|
2474
|
+
}
|
|
2475
|
+
if (route.redirectTo && (route.component || route.loadComponent)) {
|
|
2476
|
+
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and component/loadComponent cannot be used together`);
|
|
2477
|
+
}
|
|
2478
|
+
if (route.component && route.loadComponent) {
|
|
2479
|
+
throw new Error(`Invalid configuration of route '${fullPath}': component and loadComponent cannot be used together`);
|
|
2480
|
+
}
|
|
2481
|
+
if (route.redirectTo && route.canActivate) {
|
|
2482
|
+
throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and canActivate cannot be used together. Redirects happen before activation ` +
|
|
2483
|
+
`so canActivate will never be executed.`);
|
|
2484
|
+
}
|
|
2485
|
+
if (route.path && route.matcher) {
|
|
2486
|
+
throw new Error(`Invalid configuration of route '${fullPath}': path and matcher cannot be used together`);
|
|
2487
|
+
}
|
|
2488
|
+
if (route.redirectTo === void 0 && !route.component && !route.loadComponent &&
|
|
2489
|
+
!route.children && !route.loadChildren) {
|
|
2490
|
+
throw new Error(`Invalid configuration of route '${fullPath}'. One of the following must be provided: component, loadComponent, redirectTo, children or loadChildren`);
|
|
2491
|
+
}
|
|
2492
|
+
if (route.path === void 0 && route.matcher === void 0) {
|
|
2493
|
+
throw new Error(`Invalid configuration of route '${fullPath}': routes must have either a path or a matcher specified`);
|
|
2494
|
+
}
|
|
2495
|
+
if (typeof route.path === 'string' && route.path.charAt(0) === '/') {
|
|
2496
|
+
throw new Error(`Invalid configuration of route '${fullPath}': path cannot start with a slash`);
|
|
2497
|
+
}
|
|
2498
|
+
if (route.path === '' && route.redirectTo !== void 0 && route.pathMatch === void 0) {
|
|
2499
|
+
const exp = `The default value of 'pathMatch' is 'prefix', but often the intent is to use 'full'.`;
|
|
2500
|
+
throw new Error(`Invalid configuration of route '{path: "${fullPath}", redirectTo: "${route.redirectTo}"}': please provide 'pathMatch'. ${exp}`);
|
|
2501
|
+
}
|
|
2502
|
+
if (requireStandaloneComponents) {
|
|
2503
|
+
assertStandalone(fullPath, route.component);
|
|
2504
|
+
}
|
|
2505
|
+
}
|
|
2506
|
+
if (route.children) {
|
|
2507
|
+
validateConfig(route.children, fullPath, requireStandaloneComponents);
|
|
2508
|
+
}
|
|
2509
|
+
}
|
|
2510
|
+
function getFullPath(parentPath, currentRoute) {
|
|
2511
|
+
if (!currentRoute) {
|
|
2512
|
+
return parentPath;
|
|
2513
|
+
}
|
|
2514
|
+
if (!parentPath && !currentRoute.path) {
|
|
2515
|
+
return '';
|
|
2516
|
+
}
|
|
2517
|
+
else if (parentPath && !currentRoute.path) {
|
|
2518
|
+
return `${parentPath}/`;
|
|
2519
|
+
}
|
|
2520
|
+
else if (!parentPath && currentRoute.path) {
|
|
2521
|
+
return currentRoute.path;
|
|
2522
|
+
}
|
|
2523
|
+
else {
|
|
2524
|
+
return `${parentPath}/${currentRoute.path}`;
|
|
2525
|
+
}
|
|
2526
|
+
}
|
|
2527
|
+
/**
|
|
2528
|
+
* Makes a copy of the config and adds any default required properties.
|
|
2529
|
+
*/
|
|
2530
|
+
function standardizeConfig(r) {
|
|
2531
|
+
const children = r.children && r.children.map(standardizeConfig);
|
|
2532
|
+
const c = children ? { ...r, children } : { ...r };
|
|
2533
|
+
if ((!c.component && !c.loadComponent) && (children || c.loadChildren) &&
|
|
2534
|
+
(c.outlet && c.outlet !== PRIMARY_OUTLET)) {
|
|
2535
|
+
c.component = ɵEmptyOutletComponent;
|
|
2536
|
+
}
|
|
2537
|
+
return c;
|
|
2538
|
+
}
|
|
2539
|
+
/** Returns the `route.outlet` or PRIMARY_OUTLET if none exists. */
|
|
2540
|
+
function getOutlet(route) {
|
|
2541
|
+
return route.outlet || PRIMARY_OUTLET;
|
|
2542
|
+
}
|
|
2543
|
+
/**
|
|
2544
|
+
* Sorts the `routes` such that the ones with an outlet matching `outletName` come first.
|
|
2545
|
+
* The order of the configs is otherwise preserved.
|
|
2546
|
+
*/
|
|
2547
|
+
function sortByMatchingOutlets(routes, outletName) {
|
|
2548
|
+
const sortedConfig = routes.filter(r => getOutlet(r) === outletName);
|
|
2549
|
+
sortedConfig.push(...routes.filter(r => getOutlet(r) !== outletName));
|
|
2550
|
+
return sortedConfig;
|
|
2551
|
+
}
|
|
2552
|
+
/**
|
|
2553
|
+
* Gets the first injector in the snapshot's parent tree.
|
|
2554
|
+
*
|
|
2555
|
+
* If the `Route` has a static list of providers, the returned injector will be the one created from
|
|
2556
|
+
* those. If it does not exist, the returned injector may come from the parents, which may be from a
|
|
2557
|
+
* loaded config or their static providers.
|
|
2558
|
+
*
|
|
2559
|
+
* Returns `null` if there is neither this nor any parents have a stored injector.
|
|
2560
|
+
*
|
|
2561
|
+
* Generally used for retrieving the injector to use for getting tokens for guards/resolvers and
|
|
2562
|
+
* also used for getting the correct injector to use for creating components.
|
|
2563
|
+
*/
|
|
2564
|
+
function getClosestRouteInjector(snapshot) {
|
|
2565
|
+
if (!snapshot)
|
|
2566
|
+
return null;
|
|
2567
|
+
// If the current route has its own injector, which is created from the static providers on the
|
|
2568
|
+
// route itself, we should use that. Otherwise, we start at the parent since we do not want to
|
|
2569
|
+
// include the lazy loaded injector from this route.
|
|
2570
|
+
if (snapshot.routeConfig?._injector) {
|
|
2571
|
+
return snapshot.routeConfig._injector;
|
|
2572
|
+
}
|
|
2573
|
+
for (let s = snapshot.parent; s; s = s.parent) {
|
|
2574
|
+
const route = s.routeConfig;
|
|
2575
|
+
// Note that the order here is important. `_loadedInjector` stored on the route with
|
|
2576
|
+
// `loadChildren: () => NgModule` so it applies to child routes with priority. The `_injector`
|
|
2577
|
+
// is created from the static providers on that parent route, so it applies to the children as
|
|
2578
|
+
// well, but only if there is no lazy loaded NgModuleRef injector.
|
|
2579
|
+
if (route?._loadedInjector)
|
|
2580
|
+
return route._loadedInjector;
|
|
2581
|
+
if (route?._injector)
|
|
2582
|
+
return route._injector;
|
|
2583
|
+
}
|
|
2584
|
+
return null;
|
|
2585
|
+
}
|
|
2586
|
+
|
|
2587
|
+
/**
|
|
2588
|
+
* @license
|
|
2589
|
+
* Copyright Google LLC All Rights Reserved.
|
|
2590
|
+
*
|
|
2591
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
2592
|
+
* found in the LICENSE file at https://angular.io/license
|
|
2593
|
+
*/
|
|
2594
|
+
const activateRoutes = (rootContexts, routeReuseStrategy, forwardEvent) => map(t => {
|
|
2595
|
+
new ActivateRoutes(routeReuseStrategy, t.targetRouterState, t.currentRouterState, forwardEvent)
|
|
2596
|
+
.activate(rootContexts);
|
|
2597
|
+
return t;
|
|
2598
|
+
});
|
|
2599
|
+
class ActivateRoutes {
|
|
2600
|
+
constructor(routeReuseStrategy, futureState, currState, forwardEvent) {
|
|
2601
|
+
this.routeReuseStrategy = routeReuseStrategy;
|
|
2602
|
+
this.futureState = futureState;
|
|
2603
|
+
this.currState = currState;
|
|
2604
|
+
this.forwardEvent = forwardEvent;
|
|
2605
|
+
}
|
|
2606
|
+
activate(parentContexts) {
|
|
2607
|
+
const futureRoot = this.futureState._root;
|
|
2608
|
+
const currRoot = this.currState ? this.currState._root : null;
|
|
2609
|
+
this.deactivateChildRoutes(futureRoot, currRoot, parentContexts);
|
|
2610
|
+
advanceActivatedRoute(this.futureState.root);
|
|
2611
|
+
this.activateChildRoutes(futureRoot, currRoot, parentContexts);
|
|
2612
|
+
}
|
|
2613
|
+
// De-activate the child route that are not re-used for the future state
|
|
2614
|
+
deactivateChildRoutes(futureNode, currNode, contexts) {
|
|
2615
|
+
const children = nodeChildrenAsMap(currNode);
|
|
2616
|
+
// Recurse on the routes active in the future state to de-activate deeper children
|
|
2617
|
+
futureNode.children.forEach(futureChild => {
|
|
2618
|
+
const childOutletName = futureChild.value.outlet;
|
|
2619
|
+
this.deactivateRoutes(futureChild, children[childOutletName], contexts);
|
|
2620
|
+
delete children[childOutletName];
|
|
2621
|
+
});
|
|
2622
|
+
// De-activate the routes that will not be re-used
|
|
2623
|
+
forEach(children, (v, childName) => {
|
|
2624
|
+
this.deactivateRouteAndItsChildren(v, contexts);
|
|
2625
|
+
});
|
|
2626
|
+
}
|
|
2627
|
+
deactivateRoutes(futureNode, currNode, parentContext) {
|
|
2628
|
+
const future = futureNode.value;
|
|
2629
|
+
const curr = currNode ? currNode.value : null;
|
|
2630
|
+
if (future === curr) {
|
|
2631
|
+
// Reusing the node, check to see if the children need to be de-activated
|
|
2632
|
+
if (future.component) {
|
|
2633
|
+
// If we have a normal route, we need to go through an outlet.
|
|
2634
|
+
const context = parentContext.getContext(future.outlet);
|
|
2635
|
+
if (context) {
|
|
2636
|
+
this.deactivateChildRoutes(futureNode, currNode, context.children);
|
|
2637
|
+
}
|
|
2638
|
+
}
|
|
2639
|
+
else {
|
|
2640
|
+
// if we have a componentless route, we recurse but keep the same outlet map.
|
|
2641
|
+
this.deactivateChildRoutes(futureNode, currNode, parentContext);
|
|
2642
|
+
}
|
|
2643
|
+
}
|
|
2644
|
+
else {
|
|
2645
|
+
if (curr) {
|
|
2646
|
+
// Deactivate the current route which will not be re-used
|
|
2647
|
+
this.deactivateRouteAndItsChildren(currNode, parentContext);
|
|
2648
|
+
}
|
|
2649
|
+
}
|
|
2650
|
+
}
|
|
2651
|
+
deactivateRouteAndItsChildren(route, parentContexts) {
|
|
2652
|
+
// If there is no component, the Route is never attached to an outlet (because there is no
|
|
2653
|
+
// component to attach).
|
|
2654
|
+
if (route.value.component && this.routeReuseStrategy.shouldDetach(route.value.snapshot)) {
|
|
2655
|
+
this.detachAndStoreRouteSubtree(route, parentContexts);
|
|
2656
|
+
}
|
|
2657
|
+
else {
|
|
2658
|
+
this.deactivateRouteAndOutlet(route, parentContexts);
|
|
2659
|
+
}
|
|
2660
|
+
}
|
|
2661
|
+
detachAndStoreRouteSubtree(route, parentContexts) {
|
|
2662
|
+
const context = parentContexts.getContext(route.value.outlet);
|
|
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
|
+
const componentRef = context.outlet.detach();
|
|
2670
|
+
const contexts = context.children.onOutletDeactivated();
|
|
2671
|
+
this.routeReuseStrategy.store(route.value.snapshot, { componentRef, route, contexts });
|
|
2672
|
+
}
|
|
2673
|
+
}
|
|
2674
|
+
deactivateRouteAndOutlet(route, parentContexts) {
|
|
2675
|
+
const context = parentContexts.getContext(route.value.outlet);
|
|
2676
|
+
// The context could be `null` if we are on a componentless route but there may still be
|
|
2677
|
+
// children that need deactivating.
|
|
2678
|
+
const contexts = context && route.value.component ? context.children : parentContexts;
|
|
2679
|
+
const children = nodeChildrenAsMap(route);
|
|
2680
|
+
for (const childOutlet of Object.keys(children)) {
|
|
2681
|
+
this.deactivateRouteAndItsChildren(children[childOutlet], contexts);
|
|
2682
|
+
}
|
|
2683
|
+
if (context && context.outlet) {
|
|
2684
|
+
// Destroy the component
|
|
2685
|
+
context.outlet.deactivate();
|
|
2686
|
+
// Destroy the contexts for all the outlets that were in the component
|
|
2687
|
+
context.children.onOutletDeactivated();
|
|
2688
|
+
// Clear the information about the attached component on the context but keep the reference to
|
|
2689
|
+
// the outlet.
|
|
2690
|
+
context.attachRef = null;
|
|
2691
|
+
context.resolver = null;
|
|
2692
|
+
context.route = null;
|
|
2693
|
+
}
|
|
2694
|
+
}
|
|
2695
|
+
activateChildRoutes(futureNode, currNode, contexts) {
|
|
2696
|
+
const children = nodeChildrenAsMap(currNode);
|
|
2697
|
+
futureNode.children.forEach(c => {
|
|
2698
|
+
this.activateRoutes(c, children[c.value.outlet], contexts);
|
|
2699
|
+
this.forwardEvent(new ActivationEnd(c.value.snapshot));
|
|
2700
|
+
});
|
|
2701
|
+
if (futureNode.children.length) {
|
|
2702
|
+
this.forwardEvent(new ChildActivationEnd(futureNode.value.snapshot));
|
|
2703
|
+
}
|
|
2704
|
+
}
|
|
2705
|
+
activateRoutes(futureNode, currNode, parentContexts) {
|
|
2706
|
+
const future = futureNode.value;
|
|
2707
|
+
const curr = currNode ? currNode.value : null;
|
|
2708
|
+
advanceActivatedRoute(future);
|
|
2709
|
+
// reusing the node
|
|
2710
|
+
if (future === curr) {
|
|
2711
|
+
if (future.component) {
|
|
2712
|
+
// If we have a normal route, we need to go through an outlet.
|
|
2713
|
+
const context = parentContexts.getOrCreateContext(future.outlet);
|
|
2714
|
+
this.activateChildRoutes(futureNode, currNode, context.children);
|
|
2715
|
+
}
|
|
2716
|
+
else {
|
|
2717
|
+
// if we have a componentless route, we recurse but keep the same outlet map.
|
|
2718
|
+
this.activateChildRoutes(futureNode, currNode, parentContexts);
|
|
2719
|
+
}
|
|
2720
|
+
}
|
|
2721
|
+
else {
|
|
2722
|
+
if (future.component) {
|
|
2723
|
+
// if we have a normal route, we need to place the component into the outlet and recurse.
|
|
2724
|
+
const context = parentContexts.getOrCreateContext(future.outlet);
|
|
2725
|
+
if (this.routeReuseStrategy.shouldAttach(future.snapshot)) {
|
|
2726
|
+
const stored = this.routeReuseStrategy.retrieve(future.snapshot);
|
|
2727
|
+
this.routeReuseStrategy.store(future.snapshot, null);
|
|
2728
|
+
context.children.onOutletReAttached(stored.contexts);
|
|
2729
|
+
context.attachRef = stored.componentRef;
|
|
2730
|
+
context.route = stored.route.value;
|
|
2731
|
+
if (context.outlet) {
|
|
2732
|
+
// Attach right away when the outlet has already been instantiated
|
|
2733
|
+
// Otherwise attach from `RouterOutlet.ngOnInit` when it is instantiated
|
|
2734
|
+
context.outlet.attach(stored.componentRef, stored.route.value);
|
|
2735
|
+
}
|
|
2736
|
+
advanceActivatedRoute(stored.route.value);
|
|
2737
|
+
this.activateChildRoutes(futureNode, null, context.children);
|
|
2738
|
+
}
|
|
2739
|
+
else {
|
|
2740
|
+
const injector = getClosestRouteInjector(future.snapshot);
|
|
2741
|
+
const cmpFactoryResolver = injector?.get(ComponentFactoryResolver) ?? null;
|
|
2742
|
+
context.attachRef = null;
|
|
2743
|
+
context.route = future;
|
|
2744
|
+
context.resolver = cmpFactoryResolver;
|
|
2745
|
+
context.injector = injector;
|
|
2746
|
+
if (context.outlet) {
|
|
2747
|
+
// Activate the outlet when it has already been instantiated
|
|
2748
|
+
// Otherwise it will get activated from its `ngOnInit` when instantiated
|
|
2749
|
+
context.outlet.activateWith(future, context.injector);
|
|
2750
|
+
}
|
|
2751
|
+
this.activateChildRoutes(futureNode, null, context.children);
|
|
2752
|
+
}
|
|
2753
|
+
}
|
|
2754
|
+
else {
|
|
2755
|
+
// if we have a componentless route, we recurse but keep the same outlet map.
|
|
2756
|
+
this.activateChildRoutes(futureNode, null, parentContexts);
|
|
2757
|
+
}
|
|
2758
|
+
}
|
|
2564
2759
|
}
|
|
2565
2760
|
}
|
|
2566
2761
|
|
|
@@ -2572,22 +2767,39 @@ class OutletInjector {
|
|
|
2572
2767
|
* found in the LICENSE file at https://angular.io/license
|
|
2573
2768
|
*/
|
|
2574
2769
|
/**
|
|
2575
|
-
*
|
|
2576
|
-
* router-outlet is needed. For example, with a config such as:
|
|
2770
|
+
* Simple function check, but generic so type inference will flow. Example:
|
|
2577
2771
|
*
|
|
2578
|
-
*
|
|
2772
|
+
* function product(a: number, b: number) {
|
|
2773
|
+
* return a * b;
|
|
2774
|
+
* }
|
|
2579
2775
|
*
|
|
2580
|
-
*
|
|
2581
|
-
*
|
|
2776
|
+
* if (isFunction<product>(fn)) {
|
|
2777
|
+
* return fn(1, 2);
|
|
2778
|
+
* } else {
|
|
2779
|
+
* throw "Must provide the `product` function";
|
|
2780
|
+
* }
|
|
2582
2781
|
*/
|
|
2583
|
-
|
|
2782
|
+
function isFunction(v) {
|
|
2783
|
+
return typeof v === 'function';
|
|
2784
|
+
}
|
|
2785
|
+
function isBoolean(v) {
|
|
2786
|
+
return typeof v === 'boolean';
|
|
2787
|
+
}
|
|
2788
|
+
function isUrlTree(v) {
|
|
2789
|
+
return v instanceof UrlTree;
|
|
2790
|
+
}
|
|
2791
|
+
function isCanLoad(guard) {
|
|
2792
|
+
return guard && isFunction(guard.canLoad);
|
|
2793
|
+
}
|
|
2794
|
+
function isCanActivate(guard) {
|
|
2795
|
+
return guard && isFunction(guard.canActivate);
|
|
2796
|
+
}
|
|
2797
|
+
function isCanActivateChild(guard) {
|
|
2798
|
+
return guard && isFunction(guard.canActivateChild);
|
|
2799
|
+
}
|
|
2800
|
+
function isCanDeactivate(guard) {
|
|
2801
|
+
return guard && isFunction(guard.canDeactivate);
|
|
2584
2802
|
}
|
|
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
2803
|
|
|
2592
2804
|
/**
|
|
2593
2805
|
* @license
|
|
@@ -2596,113 +2808,36 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9",
|
|
|
2596
2808
|
* Use of this source code is governed by an MIT-style license that can be
|
|
2597
2809
|
* found in the LICENSE file at https://angular.io/license
|
|
2598
2810
|
*/
|
|
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;
|
|
2811
|
+
const INITIAL_VALUE = Symbol('INITIAL_VALUE');
|
|
2812
|
+
function prioritizedGuardValue() {
|
|
2813
|
+
return switchMap(obs => {
|
|
2814
|
+
return combineLatest(obs.map(o => o.pipe(take(1), startWith(INITIAL_VALUE))))
|
|
2815
|
+
.pipe(scan((acc, list) => {
|
|
2816
|
+
let isPending = false;
|
|
2817
|
+
return list.reduce((innerAcc, val, i) => {
|
|
2818
|
+
if (innerAcc !== INITIAL_VALUE)
|
|
2819
|
+
return innerAcc;
|
|
2820
|
+
// Toggle pending flag if any values haven't been set yet
|
|
2821
|
+
if (val === INITIAL_VALUE)
|
|
2822
|
+
isPending = true;
|
|
2823
|
+
// Any other return values are only valid if we haven't yet hit a pending
|
|
2824
|
+
// call. This guarantees that in the case of a guard at the bottom of the
|
|
2825
|
+
// tree that returns a redirect, we will wait for the higher priority
|
|
2826
|
+
// guard at the top to finish before performing the redirect.
|
|
2827
|
+
if (!isPending) {
|
|
2828
|
+
// Early return when we hit a `false` value as that should always
|
|
2829
|
+
// cancel navigation
|
|
2830
|
+
if (val === false)
|
|
2831
|
+
return val;
|
|
2832
|
+
if (i === list.length - 1 || isUrlTree(val)) {
|
|
2833
|
+
return val;
|
|
2834
|
+
}
|
|
2835
|
+
}
|
|
2836
|
+
return innerAcc;
|
|
2837
|
+
}, acc);
|
|
2838
|
+
}, INITIAL_VALUE), filter(item => item !== INITIAL_VALUE), map(item => isUrlTree(item) ? item : item === true), //
|
|
2839
|
+
take(1));
|
|
2840
|
+
});
|
|
2706
2841
|
}
|
|
2707
2842
|
|
|
2708
2843
|
/**
|
|
@@ -2780,6 +2915,9 @@ function addEmptyPathsToChildrenIfNeeded(segmentGroup, consumedSegments, slicedS
|
|
|
2780
2915
|
s._sourceSegment = segmentGroup;
|
|
2781
2916
|
if (relativeLinkResolution === 'legacy') {
|
|
2782
2917
|
s._segmentIndexShift = segmentGroup.segments.length;
|
|
2918
|
+
if (typeof ngDevMode === 'undefined' || !!ngDevMode) {
|
|
2919
|
+
s._segmentIndexShiftCorrected = consumedSegments.length;
|
|
2920
|
+
}
|
|
2783
2921
|
}
|
|
2784
2922
|
else {
|
|
2785
2923
|
s._segmentIndexShift = consumedSegments.length;
|
|
@@ -2880,17 +3018,17 @@ function canLoadFails(route) {
|
|
|
2880
3018
|
*
|
|
2881
3019
|
* Lazy modules are loaded along the way.
|
|
2882
3020
|
*/
|
|
2883
|
-
function applyRedirects$1(
|
|
2884
|
-
return new ApplyRedirects(
|
|
3021
|
+
function applyRedirects$1(injector, configLoader, urlSerializer, urlTree, config) {
|
|
3022
|
+
return new ApplyRedirects(injector, configLoader, urlSerializer, urlTree, config).apply();
|
|
2885
3023
|
}
|
|
2886
3024
|
class ApplyRedirects {
|
|
2887
|
-
constructor(
|
|
3025
|
+
constructor(injector, configLoader, urlSerializer, urlTree, config) {
|
|
3026
|
+
this.injector = injector;
|
|
2888
3027
|
this.configLoader = configLoader;
|
|
2889
3028
|
this.urlSerializer = urlSerializer;
|
|
2890
3029
|
this.urlTree = urlTree;
|
|
2891
3030
|
this.config = config;
|
|
2892
3031
|
this.allowRedirects = true;
|
|
2893
|
-
this.ngModule = moduleInjector.get(NgModuleRef);
|
|
2894
3032
|
}
|
|
2895
3033
|
apply() {
|
|
2896
3034
|
const splitGroup = split(this.urlTree.root, [], [], this.config).segmentGroup;
|
|
@@ -2901,7 +3039,7 @@ class ApplyRedirects {
|
|
|
2901
3039
|
// them. We should be able to remove this logic as a "breaking change" but should do some more
|
|
2902
3040
|
// investigation into the failures first.
|
|
2903
3041
|
const rootSegmentGroup = new UrlSegmentGroup(splitGroup.segments, splitGroup.children);
|
|
2904
|
-
const expanded$ = this.expandSegmentGroup(this.
|
|
3042
|
+
const expanded$ = this.expandSegmentGroup(this.injector, this.config, rootSegmentGroup, PRIMARY_OUTLET);
|
|
2905
3043
|
const urlTrees$ = expanded$.pipe(map((rootSegmentGroup) => {
|
|
2906
3044
|
return this.createUrlTree(squashSegmentGroup(rootSegmentGroup), this.urlTree.queryParams, this.urlTree.fragment);
|
|
2907
3045
|
}));
|
|
@@ -2920,7 +3058,7 @@ class ApplyRedirects {
|
|
|
2920
3058
|
}));
|
|
2921
3059
|
}
|
|
2922
3060
|
match(tree) {
|
|
2923
|
-
const expanded$ = this.expandSegmentGroup(this.
|
|
3061
|
+
const expanded$ = this.expandSegmentGroup(this.injector, this.config, tree.root, PRIMARY_OUTLET);
|
|
2924
3062
|
const mapped$ = expanded$.pipe(map((rootSegmentGroup) => {
|
|
2925
3063
|
return this.createUrlTree(squashSegmentGroup(rootSegmentGroup), tree.queryParams, tree.fragment);
|
|
2926
3064
|
}));
|
|
@@ -2940,15 +3078,15 @@ class ApplyRedirects {
|
|
|
2940
3078
|
rootCandidate;
|
|
2941
3079
|
return new UrlTree(root, queryParams, fragment);
|
|
2942
3080
|
}
|
|
2943
|
-
expandSegmentGroup(
|
|
3081
|
+
expandSegmentGroup(injector, routes, segmentGroup, outlet) {
|
|
2944
3082
|
if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) {
|
|
2945
|
-
return this.expandChildren(
|
|
3083
|
+
return this.expandChildren(injector, routes, segmentGroup)
|
|
2946
3084
|
.pipe(map((children) => new UrlSegmentGroup([], children)));
|
|
2947
3085
|
}
|
|
2948
|
-
return this.expandSegment(
|
|
3086
|
+
return this.expandSegment(injector, segmentGroup, routes, segmentGroup.segments, outlet, true);
|
|
2949
3087
|
}
|
|
2950
3088
|
// Recursively expand segment groups for all the child outlets
|
|
2951
|
-
expandChildren(
|
|
3089
|
+
expandChildren(injector, routes, segmentGroup) {
|
|
2952
3090
|
// Expand outlets one at a time, starting with the primary outlet. We need to do it this way
|
|
2953
3091
|
// because an absolute redirect from the primary outlet takes precedence.
|
|
2954
3092
|
const childOutlets = [];
|
|
@@ -2967,16 +3105,16 @@ class ApplyRedirects {
|
|
|
2967
3105
|
// first, followed by routes for other outlets, which might match if they have an
|
|
2968
3106
|
// empty path.
|
|
2969
3107
|
const sortedRoutes = sortByMatchingOutlets(routes, childOutlet);
|
|
2970
|
-
return this.expandSegmentGroup(
|
|
3108
|
+
return this.expandSegmentGroup(injector, sortedRoutes, child, childOutlet)
|
|
2971
3109
|
.pipe(map(s => ({ segment: s, outlet: childOutlet })));
|
|
2972
3110
|
}), scan((children, expandedChild) => {
|
|
2973
3111
|
children[expandedChild.outlet] = expandedChild.segment;
|
|
2974
3112
|
return children;
|
|
2975
3113
|
}, {}), last$1());
|
|
2976
3114
|
}
|
|
2977
|
-
expandSegment(
|
|
2978
|
-
return from(routes).pipe(concatMap(
|
|
2979
|
-
const expanded$ = this.expandSegmentAgainstRoute(
|
|
3115
|
+
expandSegment(injector, segmentGroup, routes, segments, outlet, allowRedirects) {
|
|
3116
|
+
return from(routes).pipe(concatMap(r => {
|
|
3117
|
+
const expanded$ = this.expandSegmentAgainstRoute(injector, segmentGroup, routes, r, segments, outlet, allowRedirects);
|
|
2980
3118
|
return expanded$.pipe(catchError((e) => {
|
|
2981
3119
|
if (e instanceof NoMatch$1) {
|
|
2982
3120
|
return of(null);
|
|
@@ -2993,35 +3131,35 @@ class ApplyRedirects {
|
|
|
2993
3131
|
throw e;
|
|
2994
3132
|
}));
|
|
2995
3133
|
}
|
|
2996
|
-
expandSegmentAgainstRoute(
|
|
3134
|
+
expandSegmentAgainstRoute(injector, segmentGroup, routes, route, paths, outlet, allowRedirects) {
|
|
2997
3135
|
if (!isImmediateMatch(route, segmentGroup, paths, outlet)) {
|
|
2998
3136
|
return noMatch(segmentGroup);
|
|
2999
3137
|
}
|
|
3000
3138
|
if (route.redirectTo === undefined) {
|
|
3001
|
-
return this.matchSegmentAgainstRoute(
|
|
3139
|
+
return this.matchSegmentAgainstRoute(injector, segmentGroup, route, paths, outlet);
|
|
3002
3140
|
}
|
|
3003
3141
|
if (allowRedirects && this.allowRedirects) {
|
|
3004
|
-
return this.expandSegmentAgainstRouteUsingRedirect(
|
|
3142
|
+
return this.expandSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, paths, outlet);
|
|
3005
3143
|
}
|
|
3006
3144
|
return noMatch(segmentGroup);
|
|
3007
3145
|
}
|
|
3008
|
-
expandSegmentAgainstRouteUsingRedirect(
|
|
3146
|
+
expandSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet) {
|
|
3009
3147
|
if (route.path === '**') {
|
|
3010
|
-
return this.expandWildCardWithParamsAgainstRouteUsingRedirect(
|
|
3148
|
+
return this.expandWildCardWithParamsAgainstRouteUsingRedirect(injector, routes, route, outlet);
|
|
3011
3149
|
}
|
|
3012
|
-
return this.expandRegularSegmentAgainstRouteUsingRedirect(
|
|
3150
|
+
return this.expandRegularSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet);
|
|
3013
3151
|
}
|
|
3014
|
-
expandWildCardWithParamsAgainstRouteUsingRedirect(
|
|
3152
|
+
expandWildCardWithParamsAgainstRouteUsingRedirect(injector, routes, route, outlet) {
|
|
3015
3153
|
const newTree = this.applyRedirectCommands([], route.redirectTo, {});
|
|
3016
3154
|
if (route.redirectTo.startsWith('/')) {
|
|
3017
3155
|
return absoluteRedirect(newTree);
|
|
3018
3156
|
}
|
|
3019
3157
|
return this.lineralizeSegments(route, newTree).pipe(mergeMap((newSegments) => {
|
|
3020
3158
|
const group = new UrlSegmentGroup(newSegments, {});
|
|
3021
|
-
return this.expandSegment(
|
|
3159
|
+
return this.expandSegment(injector, group, routes, newSegments, outlet, false);
|
|
3022
3160
|
}));
|
|
3023
3161
|
}
|
|
3024
|
-
expandRegularSegmentAgainstRouteUsingRedirect(
|
|
3162
|
+
expandRegularSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet) {
|
|
3025
3163
|
const { matched, consumedSegments, remainingSegments, positionalParamSegments } = match(segmentGroup, route, segments);
|
|
3026
3164
|
if (!matched)
|
|
3027
3165
|
return noMatch(segmentGroup);
|
|
@@ -3030,16 +3168,20 @@ class ApplyRedirects {
|
|
|
3030
3168
|
return absoluteRedirect(newTree);
|
|
3031
3169
|
}
|
|
3032
3170
|
return this.lineralizeSegments(route, newTree).pipe(mergeMap((newSegments) => {
|
|
3033
|
-
return this.expandSegment(
|
|
3171
|
+
return this.expandSegment(injector, segmentGroup, routes, newSegments.concat(remainingSegments), outlet, false);
|
|
3034
3172
|
}));
|
|
3035
3173
|
}
|
|
3036
|
-
matchSegmentAgainstRoute(
|
|
3174
|
+
matchSegmentAgainstRoute(injector, rawSegmentGroup, route, segments, outlet) {
|
|
3037
3175
|
if (route.path === '**') {
|
|
3176
|
+
// Only create the Route's `EnvironmentInjector` if it matches the attempted navigation
|
|
3177
|
+
injector = getOrCreateRouteInjectorIfNeeded(route, injector);
|
|
3038
3178
|
if (route.loadChildren) {
|
|
3039
|
-
const loaded$ = route.
|
|
3040
|
-
|
|
3179
|
+
const loaded$ = route._loadedRoutes ?
|
|
3180
|
+
of({ routes: route._loadedRoutes, injector: route._loadedInjector }) :
|
|
3181
|
+
this.configLoader.loadChildren(injector, route);
|
|
3041
3182
|
return loaded$.pipe(map((cfg) => {
|
|
3042
|
-
route.
|
|
3183
|
+
route._loadedRoutes = cfg.routes;
|
|
3184
|
+
route._loadedInjector = cfg.injector;
|
|
3043
3185
|
return new UrlSegmentGroup(segments, {});
|
|
3044
3186
|
}));
|
|
3045
3187
|
}
|
|
@@ -3048,55 +3190,57 @@ class ApplyRedirects {
|
|
|
3048
3190
|
const { matched, consumedSegments, remainingSegments } = match(rawSegmentGroup, route, segments);
|
|
3049
3191
|
if (!matched)
|
|
3050
3192
|
return noMatch(rawSegmentGroup);
|
|
3051
|
-
|
|
3193
|
+
// Only create the Route's `EnvironmentInjector` if it matches the attempted navigation
|
|
3194
|
+
injector = getOrCreateRouteInjectorIfNeeded(route, injector);
|
|
3195
|
+
const childConfig$ = this.getChildConfig(injector, route, segments);
|
|
3052
3196
|
return childConfig$.pipe(mergeMap((routerConfig) => {
|
|
3053
|
-
const
|
|
3197
|
+
const childInjector = routerConfig.injector ?? injector;
|
|
3054
3198
|
const childConfig = routerConfig.routes;
|
|
3055
3199
|
const { segmentGroup: splitSegmentGroup, slicedSegments } = split(rawSegmentGroup, consumedSegments, remainingSegments, childConfig);
|
|
3056
3200
|
// See comment on the other call to `split` about why this is necessary.
|
|
3057
3201
|
const segmentGroup = new UrlSegmentGroup(splitSegmentGroup.segments, splitSegmentGroup.children);
|
|
3058
3202
|
if (slicedSegments.length === 0 && segmentGroup.hasChildren()) {
|
|
3059
|
-
const expanded$ = this.expandChildren(
|
|
3203
|
+
const expanded$ = this.expandChildren(childInjector, childConfig, segmentGroup);
|
|
3060
3204
|
return expanded$.pipe(map((children) => new UrlSegmentGroup(consumedSegments, children)));
|
|
3061
3205
|
}
|
|
3062
3206
|
if (childConfig.length === 0 && slicedSegments.length === 0) {
|
|
3063
3207
|
return of(new UrlSegmentGroup(consumedSegments, {}));
|
|
3064
3208
|
}
|
|
3065
3209
|
const matchedOnOutlet = getOutlet(route) === outlet;
|
|
3066
|
-
const expanded$ = this.expandSegment(
|
|
3210
|
+
const expanded$ = this.expandSegment(childInjector, segmentGroup, childConfig, slicedSegments, matchedOnOutlet ? PRIMARY_OUTLET : outlet, true);
|
|
3067
3211
|
return expanded$.pipe(map((cs) => new UrlSegmentGroup(consumedSegments.concat(cs.segments), cs.children)));
|
|
3068
3212
|
}));
|
|
3069
3213
|
}
|
|
3070
|
-
getChildConfig(
|
|
3214
|
+
getChildConfig(injector, route, segments) {
|
|
3071
3215
|
if (route.children) {
|
|
3072
3216
|
// The children belong to the same module
|
|
3073
|
-
return of(
|
|
3217
|
+
return of({ routes: route.children, injector });
|
|
3074
3218
|
}
|
|
3075
3219
|
if (route.loadChildren) {
|
|
3076
3220
|
// lazy children belong to the loaded module
|
|
3077
|
-
if (route.
|
|
3078
|
-
return of(route.
|
|
3221
|
+
if (route._loadedRoutes !== undefined) {
|
|
3222
|
+
return of({ routes: route._loadedRoutes, injector: route._loadedInjector });
|
|
3079
3223
|
}
|
|
3080
|
-
return this.runCanLoadGuards(
|
|
3224
|
+
return this.runCanLoadGuards(injector, route, segments)
|
|
3081
3225
|
.pipe(mergeMap((shouldLoadResult) => {
|
|
3082
3226
|
if (shouldLoadResult) {
|
|
3083
|
-
return this.configLoader.
|
|
3084
|
-
.pipe(
|
|
3085
|
-
route.
|
|
3086
|
-
|
|
3227
|
+
return this.configLoader.loadChildren(injector, route)
|
|
3228
|
+
.pipe(tap((cfg) => {
|
|
3229
|
+
route._loadedRoutes = cfg.routes;
|
|
3230
|
+
route._loadedInjector = cfg.injector;
|
|
3087
3231
|
}));
|
|
3088
3232
|
}
|
|
3089
3233
|
return canLoadFails(route);
|
|
3090
3234
|
}));
|
|
3091
3235
|
}
|
|
3092
|
-
return of(
|
|
3236
|
+
return of({ routes: [], injector });
|
|
3093
3237
|
}
|
|
3094
|
-
runCanLoadGuards(
|
|
3238
|
+
runCanLoadGuards(injector, route, segments) {
|
|
3095
3239
|
const canLoad = route.canLoad;
|
|
3096
3240
|
if (!canLoad || canLoad.length === 0)
|
|
3097
3241
|
return of(true);
|
|
3098
3242
|
const canLoadObservables = canLoad.map((injectionToken) => {
|
|
3099
|
-
const guard =
|
|
3243
|
+
const guard = injector.get(injectionToken);
|
|
3100
3244
|
let guardVal;
|
|
3101
3245
|
if (isCanLoad(guard)) {
|
|
3102
3246
|
guardVal = guard.canLoad(route, segments);
|
|
@@ -3224,8 +3368,8 @@ function squashSegmentGroup(segmentGroup) {
|
|
|
3224
3368
|
* Use of this source code is governed by an MIT-style license that can be
|
|
3225
3369
|
* found in the LICENSE file at https://angular.io/license
|
|
3226
3370
|
*/
|
|
3227
|
-
function applyRedirects(
|
|
3228
|
-
return switchMap(t => applyRedirects$1(
|
|
3371
|
+
function applyRedirects(environmentInjector, configLoader, urlSerializer, config) {
|
|
3372
|
+
return switchMap(t => applyRedirects$1(environmentInjector, configLoader, urlSerializer, t.extractedUrl, config)
|
|
3229
3373
|
.pipe(map(urlAfterRedirects => ({ ...t, urlAfterRedirects }))));
|
|
3230
3374
|
}
|
|
3231
3375
|
|
|
@@ -3259,21 +3403,11 @@ function getCanActivateChild(p) {
|
|
|
3259
3403
|
return null;
|
|
3260
3404
|
return { node: p, guards: canActivateChild };
|
|
3261
3405
|
}
|
|
3262
|
-
function getToken(token, snapshot,
|
|
3263
|
-
const
|
|
3264
|
-
const injector =
|
|
3406
|
+
function getToken(token, snapshot, fallbackInjector) {
|
|
3407
|
+
const routeInjector = getClosestRouteInjector(snapshot);
|
|
3408
|
+
const injector = routeInjector ?? fallbackInjector;
|
|
3265
3409
|
return injector.get(token);
|
|
3266
3410
|
}
|
|
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
3411
|
function getChildRouteGuards(futureNode, currNode, contexts, futurePath, checks = {
|
|
3278
3412
|
canDeactivateChecks: [],
|
|
3279
3413
|
canActivateChecks: []
|
|
@@ -3517,6 +3651,7 @@ function runCanDeactivate(component, currARS, currRSS, futureRSS, moduleInjector
|
|
|
3517
3651
|
* Use of this source code is governed by an MIT-style license that can be
|
|
3518
3652
|
* found in the LICENSE file at https://angular.io/license
|
|
3519
3653
|
*/
|
|
3654
|
+
const NG_DEV_MODE$2 = typeof ngDevMode === 'undefined' || !!ngDevMode;
|
|
3520
3655
|
class NoMatch {
|
|
3521
3656
|
}
|
|
3522
3657
|
function newObservableError(e) {
|
|
@@ -3632,7 +3767,13 @@ class Recognizer {
|
|
|
3632
3767
|
let remainingSegments = [];
|
|
3633
3768
|
if (route.path === '**') {
|
|
3634
3769
|
const params = segments.length > 0 ? last(segments).parameters : {};
|
|
3635
|
-
|
|
3770
|
+
const pathIndexShift = getPathIndexShift(rawSegment) + segments.length;
|
|
3771
|
+
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),
|
|
3772
|
+
// NG_DEV_MODE is used to prevent the getCorrectedPathIndexShift function from affecting
|
|
3773
|
+
// production bundle size. This value is intended only to surface a warning to users
|
|
3774
|
+
// depending on `relativeLinkResolution: 'legacy'` in dev mode.
|
|
3775
|
+
(NG_DEV_MODE$2 ? getCorrectedPathIndexShift(rawSegment) + segments.length :
|
|
3776
|
+
pathIndexShift));
|
|
3636
3777
|
}
|
|
3637
3778
|
else {
|
|
3638
3779
|
const result = match(rawSegment, route, segments);
|
|
@@ -3641,7 +3782,9 @@ class Recognizer {
|
|
|
3641
3782
|
}
|
|
3642
3783
|
consumedSegments = result.consumedSegments;
|
|
3643
3784
|
remainingSegments = result.remainingSegments;
|
|
3644
|
-
|
|
3785
|
+
const pathIndexShift = getPathIndexShift(rawSegment) + consumedSegments.length;
|
|
3786
|
+
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 :
|
|
3787
|
+
pathIndexShift));
|
|
3645
3788
|
}
|
|
3646
3789
|
const childConfig = getChildConfig(route);
|
|
3647
3790
|
const { segmentGroup, slicedSegments } = split(rawSegment, consumedSegments, remainingSegments,
|
|
@@ -3689,7 +3832,7 @@ function getChildConfig(route) {
|
|
|
3689
3832
|
return route.children;
|
|
3690
3833
|
}
|
|
3691
3834
|
if (route.loadChildren) {
|
|
3692
|
-
return route.
|
|
3835
|
+
return route._loadedRoutes;
|
|
3693
3836
|
}
|
|
3694
3837
|
return [];
|
|
3695
3838
|
}
|
|
@@ -3751,10 +3894,19 @@ function getSourceSegmentGroup(segmentGroup) {
|
|
|
3751
3894
|
}
|
|
3752
3895
|
function getPathIndexShift(segmentGroup) {
|
|
3753
3896
|
let s = segmentGroup;
|
|
3754
|
-
let res =
|
|
3897
|
+
let res = s._segmentIndexShift ?? 0;
|
|
3898
|
+
while (s._sourceSegment) {
|
|
3899
|
+
s = s._sourceSegment;
|
|
3900
|
+
res += s._segmentIndexShift ?? 0;
|
|
3901
|
+
}
|
|
3902
|
+
return res - 1;
|
|
3903
|
+
}
|
|
3904
|
+
function getCorrectedPathIndexShift(segmentGroup) {
|
|
3905
|
+
let s = segmentGroup;
|
|
3906
|
+
let res = s._segmentIndexShiftCorrected ?? s._segmentIndexShift ?? 0;
|
|
3755
3907
|
while (s._sourceSegment) {
|
|
3756
3908
|
s = s._sourceSegment;
|
|
3757
|
-
res +=
|
|
3909
|
+
res += s._segmentIndexShiftCorrected ?? s._segmentIndexShift ?? 0;
|
|
3758
3910
|
}
|
|
3759
3911
|
return res - 1;
|
|
3760
3912
|
}
|
|
@@ -3804,22 +3956,16 @@ function resolveData(paramsInheritanceStrategy, moduleInjector) {
|
|
|
3804
3956
|
function runResolve(futureARS, futureRSS, paramsInheritanceStrategy, moduleInjector) {
|
|
3805
3957
|
const config = futureARS.routeConfig;
|
|
3806
3958
|
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
|
-
}
|
|
3959
|
+
if (config?.title !== undefined && !hasStaticTitle(config)) {
|
|
3960
|
+
resolve[RouteTitle] = config.title;
|
|
3815
3961
|
}
|
|
3816
3962
|
return resolveNode(resolve, futureARS, futureRSS, moduleInjector)
|
|
3817
3963
|
.pipe(map((resolvedData) => {
|
|
3818
3964
|
futureARS._resolvedData = resolvedData;
|
|
3819
|
-
futureARS.data =
|
|
3820
|
-
|
|
3821
|
-
|
|
3822
|
-
}
|
|
3965
|
+
futureARS.data = inheritedParamsDataResolve(futureARS, paramsInheritanceStrategy).resolve;
|
|
3966
|
+
if (config && hasStaticTitle(config)) {
|
|
3967
|
+
futureARS.data[RouteTitle] = config.title;
|
|
3968
|
+
}
|
|
3823
3969
|
return null;
|
|
3824
3970
|
}));
|
|
3825
3971
|
}
|
|
@@ -3830,16 +3976,9 @@ function resolveNode(resolve, futureARS, futureRSS, moduleInjector) {
|
|
|
3830
3976
|
}
|
|
3831
3977
|
const data = {};
|
|
3832
3978
|
return from(keys).pipe(mergeMap(key => getResolver(resolve[key], futureARS, futureRSS, moduleInjector)
|
|
3833
|
-
.pipe(
|
|
3979
|
+
.pipe(first(), tap((value) => {
|
|
3834
3980
|
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
|
-
}));
|
|
3981
|
+
}))), takeLast(1), mapTo(data), catchError((e) => e instanceof EmptyError ? EMPTY : throwError(e)));
|
|
3843
3982
|
}
|
|
3844
3983
|
function getDataKeys(obj) {
|
|
3845
3984
|
return [...Object.keys(obj), ...Object.getOwnPropertySymbols(obj)];
|
|
@@ -3849,6 +3988,9 @@ function getResolver(injectionToken, futureARS, futureRSS, moduleInjector) {
|
|
|
3849
3988
|
return resolver.resolve ? wrapIntoObservable(resolver.resolve(futureARS, futureRSS)) :
|
|
3850
3989
|
wrapIntoObservable(resolver(futureARS, futureRSS));
|
|
3851
3990
|
}
|
|
3991
|
+
function hasStaticTitle(config) {
|
|
3992
|
+
return typeof config.title === 'string' || config.title === null;
|
|
3993
|
+
}
|
|
3852
3994
|
|
|
3853
3995
|
/**
|
|
3854
3996
|
* @license
|
|
@@ -3945,6 +4087,7 @@ class DefaultRouteReuseStrategy extends BaseRouteReuseStrategy {
|
|
|
3945
4087
|
* Use of this source code is governed by an MIT-style license that can be
|
|
3946
4088
|
* found in the LICENSE file at https://angular.io/license
|
|
3947
4089
|
*/
|
|
4090
|
+
const NG_DEV_MODE$1 = typeof ngDevMode === 'undefined' || !!ngDevMode;
|
|
3948
4091
|
/**
|
|
3949
4092
|
* The [DI token](guide/glossary/#di-token) for a router configuration.
|
|
3950
4093
|
*
|
|
@@ -3957,43 +4100,84 @@ class DefaultRouteReuseStrategy extends BaseRouteReuseStrategy {
|
|
|
3957
4100
|
*/
|
|
3958
4101
|
const ROUTES = new InjectionToken('ROUTES');
|
|
3959
4102
|
class RouterConfigLoader {
|
|
3960
|
-
constructor(injector, compiler
|
|
4103
|
+
constructor(injector, compiler) {
|
|
3961
4104
|
this.injector = injector;
|
|
3962
4105
|
this.compiler = compiler;
|
|
3963
|
-
this.
|
|
3964
|
-
this.
|
|
4106
|
+
this.componentLoaders = new WeakMap();
|
|
4107
|
+
this.childrenLoaders = new WeakMap();
|
|
4108
|
+
}
|
|
4109
|
+
loadComponent(route) {
|
|
4110
|
+
if (this.componentLoaders.get(route)) {
|
|
4111
|
+
return this.componentLoaders.get(route);
|
|
4112
|
+
}
|
|
4113
|
+
else if (route._loadedComponent) {
|
|
4114
|
+
return of(route._loadedComponent);
|
|
4115
|
+
}
|
|
4116
|
+
if (this.onLoadStartListener) {
|
|
4117
|
+
this.onLoadStartListener(route);
|
|
4118
|
+
}
|
|
4119
|
+
const loadRunner = wrapIntoObservable(route.loadComponent())
|
|
4120
|
+
.pipe(tap(component => {
|
|
4121
|
+
if (this.onLoadEndListener) {
|
|
4122
|
+
this.onLoadEndListener(route);
|
|
4123
|
+
}
|
|
4124
|
+
NG_DEV_MODE$1 && assertStandalone(route.path ?? '', component);
|
|
4125
|
+
route._loadedComponent = component;
|
|
4126
|
+
}), finalize(() => {
|
|
4127
|
+
this.componentLoaders.delete(route);
|
|
4128
|
+
}));
|
|
4129
|
+
// Use custom ConnectableObservable as share in runners pipe increasing the bundle size too much
|
|
4130
|
+
const loader = new ConnectableObservable(loadRunner, () => new Subject()).pipe(refCount());
|
|
4131
|
+
this.componentLoaders.set(route, loader);
|
|
4132
|
+
return loader;
|
|
3965
4133
|
}
|
|
3966
|
-
|
|
3967
|
-
if (route
|
|
3968
|
-
return route
|
|
4134
|
+
loadChildren(parentInjector, route) {
|
|
4135
|
+
if (this.childrenLoaders.get(route)) {
|
|
4136
|
+
return this.childrenLoaders.get(route);
|
|
4137
|
+
}
|
|
4138
|
+
else if (route._loadedRoutes) {
|
|
4139
|
+
return of({ routes: route._loadedRoutes, injector: route._loadedInjector });
|
|
3969
4140
|
}
|
|
3970
4141
|
if (this.onLoadStartListener) {
|
|
3971
4142
|
this.onLoadStartListener(route);
|
|
3972
4143
|
}
|
|
3973
|
-
const
|
|
3974
|
-
const loadRunner =
|
|
4144
|
+
const moduleFactoryOrRoutes$ = this.loadModuleFactoryOrRoutes(route.loadChildren);
|
|
4145
|
+
const loadRunner = moduleFactoryOrRoutes$.pipe(map((factoryOrRoutes) => {
|
|
3975
4146
|
if (this.onLoadEndListener) {
|
|
3976
4147
|
this.onLoadEndListener(route);
|
|
3977
4148
|
}
|
|
3978
|
-
|
|
3979
|
-
//
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
|
|
4149
|
+
// This injector comes from the `NgModuleRef` when lazy loading an `NgModule`. There is no
|
|
4150
|
+
// injector associated with lazy loading a `Route` array.
|
|
4151
|
+
let injector;
|
|
4152
|
+
let rawRoutes;
|
|
4153
|
+
let requireStandaloneComponents = false;
|
|
4154
|
+
if (Array.isArray(factoryOrRoutes)) {
|
|
4155
|
+
rawRoutes = factoryOrRoutes;
|
|
4156
|
+
requireStandaloneComponents = true;
|
|
4157
|
+
}
|
|
4158
|
+
else {
|
|
4159
|
+
injector = factoryOrRoutes.create(parentInjector).injector;
|
|
4160
|
+
// When loading a module that doesn't provide `RouterModule.forChild()` preloader
|
|
4161
|
+
// will get stuck in an infinite loop. The child module's Injector will look to
|
|
4162
|
+
// its parent `Injector` when it doesn't find any ROUTES so it will return routes
|
|
4163
|
+
// for it's parent module instead.
|
|
4164
|
+
rawRoutes = flatten(injector.get(ROUTES, [], InjectFlags.Self | InjectFlags.Optional));
|
|
4165
|
+
}
|
|
4166
|
+
const routes = rawRoutes.map(standardizeConfig);
|
|
4167
|
+
NG_DEV_MODE$1 && validateConfig(routes, route.path, requireStandaloneComponents);
|
|
4168
|
+
return { routes, injector };
|
|
4169
|
+
}), finalize(() => {
|
|
4170
|
+
this.childrenLoaders.delete(route);
|
|
3988
4171
|
}));
|
|
3989
4172
|
// Use custom ConnectableObservable as share in runners pipe increasing the bundle size too much
|
|
3990
|
-
|
|
4173
|
+
const loader = new ConnectableObservable(loadRunner, () => new Subject())
|
|
3991
4174
|
.pipe(refCount());
|
|
3992
|
-
|
|
4175
|
+
this.childrenLoaders.set(route, loader);
|
|
4176
|
+
return loader;
|
|
3993
4177
|
}
|
|
3994
|
-
|
|
4178
|
+
loadModuleFactoryOrRoutes(loadChildren) {
|
|
3995
4179
|
return wrapIntoObservable(loadChildren()).pipe(mergeMap((t) => {
|
|
3996
|
-
if (t instanceof NgModuleFactory) {
|
|
4180
|
+
if (t instanceof NgModuleFactory || Array.isArray(t)) {
|
|
3997
4181
|
return of(t);
|
|
3998
4182
|
}
|
|
3999
4183
|
else {
|
|
@@ -4002,6 +4186,11 @@ class RouterConfigLoader {
|
|
|
4002
4186
|
}));
|
|
4003
4187
|
}
|
|
4004
4188
|
}
|
|
4189
|
+
RouterConfigLoader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterConfigLoader, deps: [{ token: i0.Injector }, { token: i0.Compiler }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
4190
|
+
RouterConfigLoader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterConfigLoader });
|
|
4191
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterConfigLoader, decorators: [{
|
|
4192
|
+
type: Injectable
|
|
4193
|
+
}], ctorParameters: function () { return [{ type: i0.Injector }, { type: i0.Compiler }]; } });
|
|
4005
4194
|
|
|
4006
4195
|
/**
|
|
4007
4196
|
* @license
|
|
@@ -4041,6 +4230,7 @@ class DefaultUrlHandlingStrategy {
|
|
|
4041
4230
|
* Use of this source code is governed by an MIT-style license that can be
|
|
4042
4231
|
* found in the LICENSE file at https://angular.io/license
|
|
4043
4232
|
*/
|
|
4233
|
+
const NG_DEV_MODE = typeof ngDevMode === 'undefined' || !!ngDevMode;
|
|
4044
4234
|
function defaultErrorHandler(error) {
|
|
4045
4235
|
throw error;
|
|
4046
4236
|
}
|
|
@@ -4183,6 +4373,8 @@ class Router {
|
|
|
4183
4373
|
/**
|
|
4184
4374
|
* Enables a bug fix that corrects relative link resolution in components with empty paths.
|
|
4185
4375
|
* @see `RouterModule`
|
|
4376
|
+
*
|
|
4377
|
+
* @deprecated
|
|
4186
4378
|
*/
|
|
4187
4379
|
this.relativeLinkResolution = 'corrected';
|
|
4188
4380
|
/**
|
|
@@ -4210,6 +4402,9 @@ class Router {
|
|
|
4210
4402
|
this.canceledNavigationResolution = 'replace';
|
|
4211
4403
|
const onLoadStart = (r) => this.triggerEvent(new RouteConfigLoadStart(r));
|
|
4212
4404
|
const onLoadEnd = (r) => this.triggerEvent(new RouteConfigLoadEnd(r));
|
|
4405
|
+
this.configLoader = injector.get(RouterConfigLoader);
|
|
4406
|
+
this.configLoader.onLoadEndListener = onLoadEnd;
|
|
4407
|
+
this.configLoader.onLoadStartListener = onLoadStart;
|
|
4213
4408
|
this.ngModule = injector.get(NgModuleRef);
|
|
4214
4409
|
this.console = injector.get(ɵConsole);
|
|
4215
4410
|
const ngZone = injector.get(NgZone);
|
|
@@ -4218,7 +4413,6 @@ class Router {
|
|
|
4218
4413
|
this.currentUrlTree = createEmptyUrlTree();
|
|
4219
4414
|
this.rawUrlTree = this.currentUrlTree;
|
|
4220
4415
|
this.browserUrlTree = this.currentUrlTree;
|
|
4221
|
-
this.configLoader = new RouterConfigLoader(injector, compiler, onLoadStart, onLoadEnd);
|
|
4222
4416
|
this.routerState = createEmptyState(this.currentUrlTree, this.rootComponentType);
|
|
4223
4417
|
this.transitions = new BehaviorSubject({
|
|
4224
4418
|
id: 0,
|
|
@@ -4427,6 +4621,25 @@ class Router {
|
|
|
4427
4621
|
skipLocationChange: !!skipLocationChange,
|
|
4428
4622
|
replaceUrl: !!replaceUrl,
|
|
4429
4623
|
});
|
|
4624
|
+
}),
|
|
4625
|
+
// --- LOAD COMPONENTS ---
|
|
4626
|
+
switchTap((t) => {
|
|
4627
|
+
const loadComponents = (route) => {
|
|
4628
|
+
const loaders = [];
|
|
4629
|
+
if (route.routeConfig?.loadComponent &&
|
|
4630
|
+
!route.routeConfig._loadedComponent) {
|
|
4631
|
+
loaders.push(this.configLoader.loadComponent(route.routeConfig)
|
|
4632
|
+
.pipe(tap(loadedComponent => {
|
|
4633
|
+
route.component = loadedComponent;
|
|
4634
|
+
}), map(() => void 0)));
|
|
4635
|
+
}
|
|
4636
|
+
for (const child of route.children) {
|
|
4637
|
+
loaders.push(...loadComponents(child));
|
|
4638
|
+
}
|
|
4639
|
+
return loaders;
|
|
4640
|
+
};
|
|
4641
|
+
return combineLatest(loadComponents(t.targetSnapshot.root))
|
|
4642
|
+
.pipe(defaultIfEmpty(), take(1));
|
|
4430
4643
|
}), map((t) => {
|
|
4431
4644
|
const targetRouterState = createRouterState(this.routeReuseStrategy, t.targetSnapshot, t.currentRouterState);
|
|
4432
4645
|
return ({ ...t, targetRouterState });
|
|
@@ -4505,23 +4718,17 @@ class Router {
|
|
|
4505
4718
|
t.resolve(false);
|
|
4506
4719
|
}
|
|
4507
4720
|
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);
|
|
4721
|
+
const mergedTree = this.urlHandlingStrategy.merge(e.url, this.rawUrlTree);
|
|
4722
|
+
const extras = {
|
|
4723
|
+
skipLocationChange: t.extras.skipLocationChange,
|
|
4724
|
+
// The URL is already updated at this point if we have 'eager' URL
|
|
4725
|
+
// updates or if the navigation was triggered by the browser (back
|
|
4726
|
+
// button, URL bar, etc). We want to replace that item in history if
|
|
4727
|
+
// the navigation is rejected.
|
|
4728
|
+
replaceUrl: this.urlUpdateStrategy === 'eager' ||
|
|
4729
|
+
isBrowserTriggeredNavigation(t.source)
|
|
4730
|
+
};
|
|
4731
|
+
this.scheduleNavigation(mergedTree, 'imperative', null, extras, { resolve: t.resolve, reject: t.reject, promise: t.promise });
|
|
4525
4732
|
}
|
|
4526
4733
|
/* All other errors should reset to the router's internal URL reference to
|
|
4527
4734
|
* the pre-error state. */
|
|
@@ -4631,7 +4838,7 @@ class Router {
|
|
|
4631
4838
|
* ```
|
|
4632
4839
|
*/
|
|
4633
4840
|
resetConfig(config) {
|
|
4634
|
-
validateConfig(config);
|
|
4841
|
+
NG_DEV_MODE && validateConfig(config);
|
|
4635
4842
|
this.config = config.map(standardizeConfig);
|
|
4636
4843
|
this.navigated = false;
|
|
4637
4844
|
this.lastSuccessfulId = -1;
|
|
@@ -4986,9 +5193,9 @@ class Router {
|
|
|
4986
5193
|
return { navigationId };
|
|
4987
5194
|
}
|
|
4988
5195
|
}
|
|
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-
|
|
5196
|
+
Router.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: Router, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
|
|
5197
|
+
Router.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: Router });
|
|
5198
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: Router, decorators: [{
|
|
4992
5199
|
type: Injectable
|
|
4993
5200
|
}], ctorParameters: function () { return [{ type: i0.Type }, { type: UrlSerializer }, { type: ChildrenOutletContexts }, { type: i3.Location }, { type: i0.Injector }, { type: i0.Compiler }, { type: undefined }]; } });
|
|
4994
5201
|
function validateCommands(commands) {
|
|
@@ -5187,9 +5394,9 @@ class RouterLink {
|
|
|
5187
5394
|
});
|
|
5188
5395
|
}
|
|
5189
5396
|
}
|
|
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-
|
|
5397
|
+
RouterLink.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterLink, deps: [{ token: Router }, { token: ActivatedRoute }, { token: 'tabindex', attribute: true }, { token: i0.Renderer2 }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
|
|
5398
|
+
RouterLink.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.0.0-rc.2", type: RouterLink, selector: ":not(a):not(area)[routerLink]", inputs: { queryParams: "queryParams", fragment: "fragment", queryParamsHandling: "queryParamsHandling", preserveFragment: "preserveFragment", skipLocationChange: "skipLocationChange", replaceUrl: "replaceUrl", state: "state", relativeTo: "relativeTo", routerLink: "routerLink" }, host: { listeners: { "click": "onClick()" } }, usesOnChanges: true, ngImport: i0 });
|
|
5399
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterLink, decorators: [{
|
|
5193
5400
|
type: Directive,
|
|
5194
5401
|
args: [{ selector: ':not(a):not(area)[routerLink]' }]
|
|
5195
5402
|
}], ctorParameters: function () { return [{ type: Router }, { type: ActivatedRoute }, { type: undefined, decorators: [{
|
|
@@ -5306,9 +5513,9 @@ class RouterLinkWithHref {
|
|
|
5306
5513
|
});
|
|
5307
5514
|
}
|
|
5308
5515
|
}
|
|
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-
|
|
5516
|
+
RouterLinkWithHref.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterLinkWithHref, deps: [{ token: Router }, { token: ActivatedRoute }, { token: i3.LocationStrategy }], target: i0.ɵɵFactoryTarget.Directive });
|
|
5517
|
+
RouterLinkWithHref.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.0.0-rc.2", type: RouterLinkWithHref, selector: "a[routerLink],area[routerLink]", inputs: { target: "target", queryParams: "queryParams", fragment: "fragment", queryParamsHandling: "queryParamsHandling", preserveFragment: "preserveFragment", skipLocationChange: "skipLocationChange", replaceUrl: "replaceUrl", state: "state", relativeTo: "relativeTo", routerLink: "routerLink" }, host: { listeners: { "click": "onClick($event.button,$event.ctrlKey,$event.shiftKey,$event.altKey,$event.metaKey)" }, properties: { "attr.target": "this.target", "attr.href": "this.href" } }, usesOnChanges: true, ngImport: i0 });
|
|
5518
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterLinkWithHref, decorators: [{
|
|
5312
5519
|
type: Directive,
|
|
5313
5520
|
args: [{ selector: 'a[routerLink],area[routerLink]' }]
|
|
5314
5521
|
}], ctorParameters: function () { return [{ type: Router }, { type: ActivatedRoute }, { type: i3.LocationStrategy }]; }, propDecorators: { target: [{
|
|
@@ -5405,6 +5612,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9",
|
|
|
5405
5612
|
* </div>
|
|
5406
5613
|
* ```
|
|
5407
5614
|
*
|
|
5615
|
+
* The `RouterLinkActive` directive can also be used to set the aria-current attribute
|
|
5616
|
+
* to provide an alternative distinction for active elements to visually impaired users.
|
|
5617
|
+
*
|
|
5618
|
+
* For example, the following code adds the 'active' class to the Home Page link when it is
|
|
5619
|
+
* indeed active and in such case also sets its aria-current attribute to 'page':
|
|
5620
|
+
*
|
|
5621
|
+
* ```
|
|
5622
|
+
* <a routerLink="/" routerLinkActive="active" ariaCurrentWhenActive="page">Home Page</a>
|
|
5623
|
+
* ```
|
|
5624
|
+
*
|
|
5408
5625
|
* @ngModule RouterModule
|
|
5409
5626
|
*
|
|
5410
5627
|
* @publicApi
|
|
@@ -5498,6 +5715,12 @@ class RouterLinkActive {
|
|
|
5498
5715
|
this.renderer.removeClass(this.element.nativeElement, c);
|
|
5499
5716
|
}
|
|
5500
5717
|
});
|
|
5718
|
+
if (hasActiveLinks && this.ariaCurrentWhenActive !== undefined) {
|
|
5719
|
+
this.renderer.setAttribute(this.element.nativeElement, 'aria-current', this.ariaCurrentWhenActive.toString());
|
|
5720
|
+
}
|
|
5721
|
+
else {
|
|
5722
|
+
this.renderer.removeAttribute(this.element.nativeElement, 'aria-current');
|
|
5723
|
+
}
|
|
5501
5724
|
// Emit on isActiveChange after classes are updated
|
|
5502
5725
|
this.isActiveChange.emit(hasActiveLinks);
|
|
5503
5726
|
}
|
|
@@ -5517,9 +5740,9 @@ class RouterLinkActive {
|
|
|
5517
5740
|
this.links.some(isActiveCheckFn) || this.linksWithHrefs.some(isActiveCheckFn);
|
|
5518
5741
|
}
|
|
5519
5742
|
}
|
|
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-
|
|
5743
|
+
RouterLinkActive.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterLinkActive, deps: [{ token: Router }, { token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }, { token: RouterLink, optional: true }, { token: RouterLinkWithHref, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
|
|
5744
|
+
RouterLinkActive.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.0.0-rc.2", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: { routerLinkActiveOptions: "routerLinkActiveOptions", ariaCurrentWhenActive: "ariaCurrentWhenActive", routerLinkActive: "routerLinkActive" }, outputs: { isActiveChange: "isActiveChange" }, queries: [{ propertyName: "links", predicate: RouterLink, descendants: true }, { propertyName: "linksWithHrefs", predicate: RouterLinkWithHref, descendants: true }], exportAs: ["routerLinkActive"], usesOnChanges: true, ngImport: i0 });
|
|
5745
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterLinkActive, decorators: [{
|
|
5523
5746
|
type: Directive,
|
|
5524
5747
|
args: [{
|
|
5525
5748
|
selector: '[routerLinkActive]',
|
|
@@ -5537,6 +5760,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9",
|
|
|
5537
5760
|
args: [RouterLinkWithHref, { descendants: true }]
|
|
5538
5761
|
}], routerLinkActiveOptions: [{
|
|
5539
5762
|
type: Input
|
|
5763
|
+
}], ariaCurrentWhenActive: [{
|
|
5764
|
+
type: Input
|
|
5540
5765
|
}], isActiveChange: [{
|
|
5541
5766
|
type: Output
|
|
5542
5767
|
}], routerLinkActive: [{
|
|
@@ -5620,9 +5845,9 @@ class DefaultTitleStrategy extends TitleStrategy {
|
|
|
5620
5845
|
}
|
|
5621
5846
|
}
|
|
5622
5847
|
}
|
|
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-
|
|
5848
|
+
DefaultTitleStrategy.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: DefaultTitleStrategy, deps: [{ token: i1.Title }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
5849
|
+
DefaultTitleStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: DefaultTitleStrategy, providedIn: 'root' });
|
|
5850
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: DefaultTitleStrategy, decorators: [{
|
|
5626
5851
|
type: Injectable,
|
|
5627
5852
|
args: [{ providedIn: 'root' }]
|
|
5628
5853
|
}], ctorParameters: function () { return [{ type: i1.Title }]; } });
|
|
@@ -5686,13 +5911,11 @@ class NoPreloading {
|
|
|
5686
5911
|
* @publicApi
|
|
5687
5912
|
*/
|
|
5688
5913
|
class RouterPreloader {
|
|
5689
|
-
constructor(router, compiler, injector, preloadingStrategy) {
|
|
5914
|
+
constructor(router, compiler, injector, preloadingStrategy, loader) {
|
|
5690
5915
|
this.router = router;
|
|
5691
5916
|
this.injector = injector;
|
|
5692
5917
|
this.preloadingStrategy = preloadingStrategy;
|
|
5693
|
-
|
|
5694
|
-
const onEndLoad = (r) => router.triggerEvent(new RouteConfigLoadEnd(r));
|
|
5695
|
-
this.loader = new RouterConfigLoader(injector, compiler, onStartLoad, onEndLoad);
|
|
5918
|
+
this.loader = loader;
|
|
5696
5919
|
}
|
|
5697
5920
|
setUpPreloading() {
|
|
5698
5921
|
this.subscription =
|
|
@@ -5701,8 +5924,7 @@ class RouterPreloader {
|
|
|
5701
5924
|
.subscribe(() => { });
|
|
5702
5925
|
}
|
|
5703
5926
|
preload() {
|
|
5704
|
-
|
|
5705
|
-
return this.processRoutes(ngModule, this.router.config);
|
|
5927
|
+
return this.processRoutes(this.injector, this.router.config);
|
|
5706
5928
|
}
|
|
5707
5929
|
/** @nodoc */
|
|
5708
5930
|
ngOnDestroy() {
|
|
@@ -5710,41 +5932,59 @@ class RouterPreloader {
|
|
|
5710
5932
|
this.subscription.unsubscribe();
|
|
5711
5933
|
}
|
|
5712
5934
|
}
|
|
5713
|
-
processRoutes(
|
|
5935
|
+
processRoutes(injector, routes) {
|
|
5714
5936
|
const res = [];
|
|
5715
5937
|
for (const route of routes) {
|
|
5716
|
-
|
|
5717
|
-
|
|
5718
|
-
|
|
5719
|
-
res.push(this.processRoutes(childConfig.module, childConfig.routes));
|
|
5720
|
-
// no config loaded, fetch the config
|
|
5938
|
+
if (route.providers && !route._injector) {
|
|
5939
|
+
route._injector =
|
|
5940
|
+
createEnvironmentInjector(route.providers, injector, `Route: ${route.path}`);
|
|
5721
5941
|
}
|
|
5722
|
-
|
|
5723
|
-
|
|
5724
|
-
|
|
5942
|
+
const injectorForCurrentRoute = route._injector ?? injector;
|
|
5943
|
+
const injectorForChildren = route._loadedInjector ?? injectorForCurrentRoute;
|
|
5944
|
+
if ((route.loadChildren && !route._loadedRoutes) ||
|
|
5945
|
+
(route.loadComponent && !route._loadedComponent)) {
|
|
5946
|
+
res.push(this.preloadConfig(injectorForCurrentRoute, route));
|
|
5725
5947
|
}
|
|
5726
|
-
else if (route.children) {
|
|
5727
|
-
res.push(this.processRoutes(
|
|
5948
|
+
else if (route.children || route._loadedRoutes) {
|
|
5949
|
+
res.push(this.processRoutes(injectorForChildren, (route.children ?? route._loadedRoutes)));
|
|
5728
5950
|
}
|
|
5729
5951
|
}
|
|
5730
|
-
return from(res).pipe(mergeAll()
|
|
5952
|
+
return from(res).pipe(mergeAll());
|
|
5731
5953
|
}
|
|
5732
|
-
preloadConfig(
|
|
5954
|
+
preloadConfig(injector, route) {
|
|
5733
5955
|
return this.preloadingStrategy.preload(route, () => {
|
|
5734
|
-
|
|
5735
|
-
|
|
5736
|
-
|
|
5737
|
-
|
|
5738
|
-
|
|
5956
|
+
let loadedChildren$;
|
|
5957
|
+
if (route.loadChildren && route.canLoad === undefined) {
|
|
5958
|
+
loadedChildren$ = this.loader.loadChildren(injector, route);
|
|
5959
|
+
}
|
|
5960
|
+
else {
|
|
5961
|
+
loadedChildren$ = of(null);
|
|
5962
|
+
}
|
|
5963
|
+
const recursiveLoadChildren$ = loadedChildren$.pipe(mergeMap((config) => {
|
|
5964
|
+
if (config === null) {
|
|
5965
|
+
return of(void 0);
|
|
5966
|
+
}
|
|
5967
|
+
route._loadedRoutes = config.routes;
|
|
5968
|
+
route._loadedInjector = config.injector;
|
|
5969
|
+
// If the loaded config was a module, use that as the module/module injector going
|
|
5970
|
+
// forward. Otherwise, continue using the current module/module injector.
|
|
5971
|
+
return this.processRoutes(config.injector ?? injector, config.routes);
|
|
5739
5972
|
}));
|
|
5973
|
+
if (route.loadComponent && !route._loadedComponent) {
|
|
5974
|
+
const loadComponent$ = this.loader.loadComponent(route);
|
|
5975
|
+
return from([recursiveLoadChildren$, loadComponent$]).pipe(mergeAll());
|
|
5976
|
+
}
|
|
5977
|
+
else {
|
|
5978
|
+
return recursiveLoadChildren$;
|
|
5979
|
+
}
|
|
5740
5980
|
});
|
|
5741
5981
|
}
|
|
5742
5982
|
}
|
|
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-
|
|
5983
|
+
RouterPreloader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterPreloader, deps: [{ token: Router }, { token: i0.Compiler }, { token: i0.EnvironmentInjector }, { token: PreloadingStrategy }, { token: RouterConfigLoader }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
5984
|
+
RouterPreloader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterPreloader });
|
|
5985
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterPreloader, decorators: [{
|
|
5746
5986
|
type: Injectable
|
|
5747
|
-
}], ctorParameters: function () { return [{ type: Router }, { type: i0.Compiler }, { type: i0.
|
|
5987
|
+
}], ctorParameters: function () { return [{ type: Router }, { type: i0.Compiler }, { type: i0.EnvironmentInjector }, { type: PreloadingStrategy }, { type: RouterConfigLoader }]; } });
|
|
5748
5988
|
|
|
5749
5989
|
/**
|
|
5750
5990
|
* @license
|
|
@@ -5828,9 +6068,9 @@ class RouterScroller {
|
|
|
5828
6068
|
}
|
|
5829
6069
|
}
|
|
5830
6070
|
}
|
|
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-
|
|
6071
|
+
RouterScroller.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterScroller, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
|
|
6072
|
+
RouterScroller.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterScroller });
|
|
6073
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterScroller, decorators: [{
|
|
5834
6074
|
type: Injectable
|
|
5835
6075
|
}], ctorParameters: function () { return [{ type: Router }, { type: i3.ViewportScroller }, { type: undefined }]; } });
|
|
5836
6076
|
|
|
@@ -5873,6 +6113,7 @@ const ROUTER_PROVIDERS = [
|
|
|
5873
6113
|
NoPreloading,
|
|
5874
6114
|
PreloadAllModules,
|
|
5875
6115
|
{ provide: ROUTER_CONFIGURATION, useValue: { enableTracing: false } },
|
|
6116
|
+
RouterConfigLoader,
|
|
5876
6117
|
];
|
|
5877
6118
|
function routerNgProbeToken() {
|
|
5878
6119
|
return new NgProbeToken('Router', Router);
|
|
@@ -5971,10 +6212,10 @@ class RouterModule {
|
|
|
5971
6212
|
return { ngModule: RouterModule, providers: [provideRoutes(routes)] };
|
|
5972
6213
|
}
|
|
5973
6214
|
}
|
|
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-
|
|
6215
|
+
RouterModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterModule, deps: [{ token: ROUTER_FORROOT_GUARD, optional: true }, { token: Router, optional: true }], target: i0.ɵɵFactoryTarget.NgModule });
|
|
6216
|
+
RouterModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterModule, declarations: [RouterOutlet, RouterLink, RouterLinkWithHref, RouterLinkActive, ɵEmptyOutletComponent], exports: [RouterOutlet, RouterLink, RouterLinkWithHref, RouterLinkActive, ɵEmptyOutletComponent] });
|
|
6217
|
+
RouterModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterModule });
|
|
6218
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterModule, decorators: [{
|
|
5978
6219
|
type: NgModule,
|
|
5979
6220
|
args: [{
|
|
5980
6221
|
declarations: ROUTER_DIRECTIVES,
|
|
@@ -6036,11 +6277,11 @@ function setupRouter(urlSerializer, contexts, location, injector, compiler, conf
|
|
|
6036
6277
|
}
|
|
6037
6278
|
router.titleStrategy = titleStrategy ?? defaultTitleStrategy;
|
|
6038
6279
|
assignExtraOptionsToRouter(opts, router);
|
|
6039
|
-
if (opts.enableTracing) {
|
|
6280
|
+
if ((typeof ngDevMode === 'undefined' || ngDevMode) && opts.enableTracing) {
|
|
6040
6281
|
router.events.subscribe((e) => {
|
|
6041
6282
|
// tslint:disable:no-console
|
|
6042
6283
|
console.group?.(`Router Event: ${e.constructor.name}`);
|
|
6043
|
-
console.log(e
|
|
6284
|
+
console.log(stringifyEvent(e));
|
|
6044
6285
|
console.log(e);
|
|
6045
6286
|
console.groupEnd?.();
|
|
6046
6287
|
// tslint:enable:no-console
|
|
@@ -6107,9 +6348,7 @@ class RouterInitializer {
|
|
|
6107
6348
|
router.setUpLocationChangeListener();
|
|
6108
6349
|
resolve(true);
|
|
6109
6350
|
}
|
|
6110
|
-
else if (
|
|
6111
|
-
// TODO: enabled is deprecated as of v11, can be removed in v13
|
|
6112
|
-
opts.initialNavigation === 'enabled' || opts.initialNavigation === 'enabledBlocking') {
|
|
6351
|
+
else if (opts.initialNavigation === 'enabledBlocking') {
|
|
6113
6352
|
router.hooks.afterPreactivation = () => {
|
|
6114
6353
|
// only the initial navigation should be delayed
|
|
6115
6354
|
if (!this.initNavigation) {
|
|
@@ -6153,9 +6392,9 @@ class RouterInitializer {
|
|
|
6153
6392
|
this.destroyed = true;
|
|
6154
6393
|
}
|
|
6155
6394
|
}
|
|
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-
|
|
6395
|
+
RouterInitializer.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterInitializer, deps: [{ token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
6396
|
+
RouterInitializer.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterInitializer });
|
|
6397
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterInitializer, decorators: [{
|
|
6159
6398
|
type: Injectable
|
|
6160
6399
|
}], ctorParameters: function () { return [{ type: i0.Injector }]; } });
|
|
6161
6400
|
function getAppInitializer(r) {
|
|
@@ -6195,7 +6434,7 @@ function provideRouterInitializer() {
|
|
|
6195
6434
|
/**
|
|
6196
6435
|
* @publicApi
|
|
6197
6436
|
*/
|
|
6198
|
-
const VERSION = new Version('14.0.0-
|
|
6437
|
+
const VERSION = new Version('14.0.0-rc.2');
|
|
6199
6438
|
|
|
6200
6439
|
/**
|
|
6201
6440
|
* @license
|