@angular/router 12.1.0-next.3 → 12.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundles/router-testing.umd.js +11 -5
- package/bundles/router-testing.umd.js.map +1 -1
- package/bundles/router-upgrade.umd.js +1 -1
- package/bundles/router.umd.js +135 -30
- package/bundles/router.umd.js.map +1 -1
- package/esm2015/src/directives/router_link_active.js +1 -1
- package/esm2015/src/router.js +106 -22
- package/esm2015/src/router_config_loader.js +7 -2
- package/esm2015/src/router_module.js +9 -1
- package/esm2015/src/url_tree.js +5 -3
- package/esm2015/src/utils/config.js +1 -1
- package/esm2015/src/version.js +1 -1
- package/fesm2015/router.js +125 -26
- package/fesm2015/router.js.map +1 -1
- package/fesm2015/testing.js +1 -1
- package/fesm2015/upgrade.js +1 -1
- package/package.json +5 -5
- package/router.d.ts +34 -5
- package/router.metadata.json +1 -1
- package/testing/testing.d.ts +1 -1
- package/testing.d.ts +1 -1
- package/upgrade/upgrade.d.ts +1 -1
- package/upgrade.d.ts +1 -1
package/esm2015/src/version.js
CHANGED
|
@@ -14,5 +14,5 @@ import { Version } from '@angular/core';
|
|
|
14
14
|
/**
|
|
15
15
|
* @publicApi
|
|
16
16
|
*/
|
|
17
|
-
export const VERSION = new Version('12.1.0
|
|
17
|
+
export const VERSION = new Version('12.1.0');
|
|
18
18
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmVyc2lvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL3JvdXRlci9zcmMvdmVyc2lvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0dBTUc7QUFFSDs7OztHQUlHO0FBRUgsT0FBTyxFQUFDLE9BQU8sRUFBQyxNQUFNLGVBQWUsQ0FBQztBQUV0Qzs7R0FFRztBQUNILE1BQU0sQ0FBQyxNQUFNLE9BQU8sR0FBRyxJQUFJLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IEdvb2dsZSBMTEMgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuICovXG5cbi8qKlxuICogQG1vZHVsZVxuICogQGRlc2NyaXB0aW9uXG4gKiBFbnRyeSBwb2ludCBmb3IgYWxsIHB1YmxpYyBBUElzIG9mIHRoZSByb3V0ZXIgcGFja2FnZS5cbiAqL1xuXG5pbXBvcnQge1ZlcnNpb259IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG4vKipcbiAqIEBwdWJsaWNBcGlcbiAqL1xuZXhwb3J0IGNvbnN0IFZFUlNJT04gPSBuZXcgVmVyc2lvbignMC4wLjAtUExBQ0VIT0xERVInKTtcbiJdfQ==
|
package/fesm2015/router.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular v12.1.0
|
|
2
|
+
* @license Angular v12.1.0
|
|
3
3
|
* (c) 2010-2021 Google LLC. https://angular.io/
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
@@ -969,12 +969,14 @@ function serializeMatrixParams(params) {
|
|
|
969
969
|
.join('');
|
|
970
970
|
}
|
|
971
971
|
function serializeQueryParams(params) {
|
|
972
|
-
const strParams = Object.keys(params)
|
|
972
|
+
const strParams = Object.keys(params)
|
|
973
|
+
.map((name) => {
|
|
973
974
|
const value = params[name];
|
|
974
975
|
return Array.isArray(value) ?
|
|
975
976
|
value.map(v => `${encodeUriQuery(name)}=${encodeUriQuery(v)}`).join('&') :
|
|
976
977
|
`${encodeUriQuery(name)}=${encodeUriQuery(value)}`;
|
|
977
|
-
})
|
|
978
|
+
})
|
|
979
|
+
.filter(s => !!s);
|
|
978
980
|
return strParams.length ? `?${strParams.join('&')}` : '';
|
|
979
981
|
}
|
|
980
982
|
const SEGMENT_RE = /^[^\/()?;=#]+/;
|
|
@@ -3638,7 +3640,12 @@ class DefaultRouteReuseStrategy extends BaseRouteReuseStrategy {
|
|
|
3638
3640
|
*/
|
|
3639
3641
|
/**
|
|
3640
3642
|
* The [DI token](guide/glossary/#di-token) for a router configuration.
|
|
3641
|
-
*
|
|
3643
|
+
*
|
|
3644
|
+
* `ROUTES` is a low level API for router configuration via dependency injection.
|
|
3645
|
+
*
|
|
3646
|
+
* We recommend that in almost all cases to use higher level APIs such as `RouterModule.forRoot()`,
|
|
3647
|
+
* `RouterModule.forChild()`, `provideRoutes`, or `Router.resetConfig()`.
|
|
3648
|
+
*
|
|
3642
3649
|
* @publicApi
|
|
3643
3650
|
*/
|
|
3644
3651
|
const ROUTES = new InjectionToken('ROUTES');
|
|
@@ -3869,6 +3876,11 @@ class Router {
|
|
|
3869
3876
|
*/
|
|
3870
3877
|
this.lastLocationChangeInfo = null;
|
|
3871
3878
|
this.navigationId = 0;
|
|
3879
|
+
/**
|
|
3880
|
+
* The id of the currently active page in the router.
|
|
3881
|
+
* Updated to the transition's target id on a successful navigation.
|
|
3882
|
+
*/
|
|
3883
|
+
this.currentPageId = 0;
|
|
3872
3884
|
this.isNgZoneEnabled = false;
|
|
3873
3885
|
/**
|
|
3874
3886
|
* An event stream for routing events in this NgModule.
|
|
@@ -3910,8 +3922,16 @@ class Router {
|
|
|
3910
3922
|
this.routeReuseStrategy = new DefaultRouteReuseStrategy();
|
|
3911
3923
|
/**
|
|
3912
3924
|
* How to handle a navigation request to the current URL. One of:
|
|
3925
|
+
*
|
|
3913
3926
|
* - `'ignore'` : The router ignores the request.
|
|
3914
3927
|
* - `'reload'` : The router reloads the URL. Use to implement a "refresh" feature.
|
|
3928
|
+
*
|
|
3929
|
+
* Note that this only configures whether the Route reprocesses the URL and triggers related
|
|
3930
|
+
* action and events like redirects, guards, and resolvers. By default, the router re-uses a
|
|
3931
|
+
* component instance when it re-navigates to the same component type without visiting a different
|
|
3932
|
+
* component first. This behavior is configured by the `RouteReuseStrategy`. In order to reload
|
|
3933
|
+
* routed components on same url navigation, you need to set `onSameUrlNavigation` to `'reload'`
|
|
3934
|
+
* _and_ provide a `RouteReuseStrategy` which returns `false` for `shouldReuseRoute`.
|
|
3915
3935
|
*/
|
|
3916
3936
|
this.onSameUrlNavigation = 'ignore';
|
|
3917
3937
|
/**
|
|
@@ -3937,6 +3957,24 @@ class Router {
|
|
|
3937
3957
|
* @see `RouterModule`
|
|
3938
3958
|
*/
|
|
3939
3959
|
this.relativeLinkResolution = 'corrected';
|
|
3960
|
+
/**
|
|
3961
|
+
* Configures how the Router attempts to restore state when a navigation is cancelled.
|
|
3962
|
+
*
|
|
3963
|
+
* 'replace' - Always uses `location.replaceState` to set the browser state to the state of the
|
|
3964
|
+
* router before the navigation started.
|
|
3965
|
+
*
|
|
3966
|
+
* 'computed' - Will always return to the same state that corresponds to the actual Angular route
|
|
3967
|
+
* when the navigation gets cancelled right after triggering a `popstate` event.
|
|
3968
|
+
*
|
|
3969
|
+
* The default value is `replace`
|
|
3970
|
+
*
|
|
3971
|
+
* @internal
|
|
3972
|
+
*/
|
|
3973
|
+
// TODO(atscott): Determine how/when/if to make this public API
|
|
3974
|
+
// This shouldn’t be an option at all but may need to be in order to allow migration without a
|
|
3975
|
+
// breaking change. We need to determine if it should be made into public api (or if we forgo
|
|
3976
|
+
// the option and release as a breaking change bug fix in a major version).
|
|
3977
|
+
this.canceledNavigationResolution = 'replace';
|
|
3940
3978
|
const onLoadStart = (r) => this.triggerEvent(new RouteConfigLoadStart(r));
|
|
3941
3979
|
const onLoadEnd = (r) => this.triggerEvent(new RouteConfigLoadEnd(r));
|
|
3942
3980
|
this.ngModule = injector.get(NgModuleRef);
|
|
@@ -3951,6 +3989,7 @@ class Router {
|
|
|
3951
3989
|
this.routerState = createEmptyState(this.currentUrlTree, this.rootComponentType);
|
|
3952
3990
|
this.transitions = new BehaviorSubject({
|
|
3953
3991
|
id: 0,
|
|
3992
|
+
targetPageId: 0,
|
|
3954
3993
|
currentUrlTree: this.currentUrlTree,
|
|
3955
3994
|
currentRawUrl: this.currentUrlTree,
|
|
3956
3995
|
extractedUrl: this.urlHandlingStrategy.extract(this.currentUrlTree),
|
|
@@ -4023,7 +4062,7 @@ class Router {
|
|
|
4023
4062
|
tap(t => {
|
|
4024
4063
|
if (this.urlUpdateStrategy === 'eager') {
|
|
4025
4064
|
if (!t.extras.skipLocationChange) {
|
|
4026
|
-
this.setBrowserUrl(t.urlAfterRedirects,
|
|
4065
|
+
this.setBrowserUrl(t.urlAfterRedirects, t);
|
|
4027
4066
|
}
|
|
4028
4067
|
this.browserUrlTree = t.urlAfterRedirects;
|
|
4029
4068
|
}
|
|
@@ -4083,10 +4122,7 @@ class Router {
|
|
|
4083
4122
|
this.triggerEvent(guardsEnd);
|
|
4084
4123
|
}), filter(t => {
|
|
4085
4124
|
if (!t.guardsResult) {
|
|
4086
|
-
this.
|
|
4087
|
-
const navCancel = new NavigationCancel(t.id, this.serializeUrl(t.extractedUrl), '');
|
|
4088
|
-
eventsSubject.next(navCancel);
|
|
4089
|
-
t.resolve(false);
|
|
4125
|
+
this.cancelNavigationTransition(t, '');
|
|
4090
4126
|
return false;
|
|
4091
4127
|
}
|
|
4092
4128
|
return true;
|
|
@@ -4103,9 +4139,7 @@ class Router {
|
|
|
4103
4139
|
next: () => dataResolved = true,
|
|
4104
4140
|
complete: () => {
|
|
4105
4141
|
if (!dataResolved) {
|
|
4106
|
-
|
|
4107
|
-
eventsSubject.next(navCancel);
|
|
4108
|
-
t.resolve(false);
|
|
4142
|
+
this.cancelNavigationTransition(t, `At least one route resolver didn't emit any value.`);
|
|
4109
4143
|
}
|
|
4110
4144
|
}
|
|
4111
4145
|
}));
|
|
@@ -4142,7 +4176,7 @@ class Router {
|
|
|
4142
4176
|
this.routerState = t.targetRouterState;
|
|
4143
4177
|
if (this.urlUpdateStrategy === 'deferred') {
|
|
4144
4178
|
if (!t.extras.skipLocationChange) {
|
|
4145
|
-
this.setBrowserUrl(this.rawUrlTree,
|
|
4179
|
+
this.setBrowserUrl(this.rawUrlTree, t);
|
|
4146
4180
|
}
|
|
4147
4181
|
this.browserUrlTree = t.urlAfterRedirects;
|
|
4148
4182
|
}
|
|
@@ -4169,10 +4203,7 @@ class Router {
|
|
|
4169
4203
|
// sync code which looks for a value here in order to determine whether or
|
|
4170
4204
|
// not to handle a given popstate event or to leave it to the Angular
|
|
4171
4205
|
// router.
|
|
4172
|
-
this.
|
|
4173
|
-
const navCancel = new NavigationCancel(t.id, this.serializeUrl(t.extractedUrl), `Navigation ID ${t.id} is not equal to the current navigation id ${this.navigationId}`);
|
|
4174
|
-
eventsSubject.next(navCancel);
|
|
4175
|
-
t.resolve(false);
|
|
4206
|
+
this.cancelNavigationTransition(t, `Navigation ID ${t.id} is not equal to the current navigation id ${this.navigationId}`);
|
|
4176
4207
|
}
|
|
4177
4208
|
// currentNavigation should always be reset to null here. If navigation was
|
|
4178
4209
|
// successful, lastSuccessfulTransition will have already been set. Therefore
|
|
@@ -4284,6 +4315,7 @@ class Router {
|
|
|
4284
4315
|
if (state) {
|
|
4285
4316
|
const stateCopy = Object.assign({}, state);
|
|
4286
4317
|
delete stateCopy.navigationId;
|
|
4318
|
+
delete stateCopy.ɵrouterPageId;
|
|
4287
4319
|
if (Object.keys(stateCopy).length !== 0) {
|
|
4288
4320
|
extras.state = stateCopy;
|
|
4289
4321
|
}
|
|
@@ -4478,7 +4510,14 @@ class Router {
|
|
|
4478
4510
|
}
|
|
4479
4511
|
const urlTree = isUrlTree(url) ? url : this.parseUrl(url);
|
|
4480
4512
|
const mergedTree = this.urlHandlingStrategy.merge(urlTree, this.rawUrlTree);
|
|
4481
|
-
|
|
4513
|
+
let restoredState = null;
|
|
4514
|
+
if (this.canceledNavigationResolution === 'computed') {
|
|
4515
|
+
const isInitialPage = this.currentPageId === 0;
|
|
4516
|
+
if (isInitialPage || extras.skipLocationChange || extras.replaceUrl) {
|
|
4517
|
+
restoredState = this.location.getState();
|
|
4518
|
+
}
|
|
4519
|
+
}
|
|
4520
|
+
return this.scheduleNavigation(mergedTree, 'imperative', restoredState, extras);
|
|
4482
4521
|
}
|
|
4483
4522
|
/**
|
|
4484
4523
|
* Navigate based on the provided array of commands and a starting point.
|
|
@@ -4559,6 +4598,7 @@ class Router {
|
|
|
4559
4598
|
this.navigations.subscribe(t => {
|
|
4560
4599
|
this.navigated = true;
|
|
4561
4600
|
this.lastSuccessfulId = t.id;
|
|
4601
|
+
this.currentPageId = t.targetPageId;
|
|
4562
4602
|
this.events
|
|
4563
4603
|
.next(new NavigationEnd(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(this.currentUrlTree)));
|
|
4564
4604
|
this.lastSuccessfulNavigation = this.currentNavigation;
|
|
@@ -4609,8 +4649,24 @@ class Router {
|
|
|
4609
4649
|
});
|
|
4610
4650
|
}
|
|
4611
4651
|
const id = ++this.navigationId;
|
|
4652
|
+
let targetPageId;
|
|
4653
|
+
if (this.canceledNavigationResolution === 'computed') {
|
|
4654
|
+
// If the `ɵrouterPageId` exist in the state then `targetpageId` should have the value of
|
|
4655
|
+
// `ɵrouterPageId`
|
|
4656
|
+
if (restoredState && restoredState.ɵrouterPageId) {
|
|
4657
|
+
targetPageId = restoredState.ɵrouterPageId;
|
|
4658
|
+
}
|
|
4659
|
+
else {
|
|
4660
|
+
targetPageId = this.currentPageId + 1;
|
|
4661
|
+
}
|
|
4662
|
+
}
|
|
4663
|
+
else {
|
|
4664
|
+
// This is unused when `canceledNavigationResolution` is not computed.
|
|
4665
|
+
targetPageId = 0;
|
|
4666
|
+
}
|
|
4612
4667
|
this.setTransition({
|
|
4613
4668
|
id,
|
|
4669
|
+
targetPageId,
|
|
4614
4670
|
source,
|
|
4615
4671
|
restoredState,
|
|
4616
4672
|
currentUrlTree: this.currentUrlTree,
|
|
@@ -4629,15 +4685,14 @@ class Router {
|
|
|
4629
4685
|
return Promise.reject(e);
|
|
4630
4686
|
});
|
|
4631
4687
|
}
|
|
4632
|
-
setBrowserUrl(url,
|
|
4688
|
+
setBrowserUrl(url, t) {
|
|
4633
4689
|
const path = this.urlSerializer.serialize(url);
|
|
4634
|
-
state = state
|
|
4635
|
-
if (this.location.isCurrentPathEqualTo(path) || replaceUrl) {
|
|
4636
|
-
|
|
4637
|
-
this.location.replaceState(path, '', Object.assign(Object.assign({}, state), { navigationId: id }));
|
|
4690
|
+
const state = Object.assign(Object.assign({}, t.extras.state), this.generateNgRouterState(t.id, t.targetPageId));
|
|
4691
|
+
if (this.location.isCurrentPathEqualTo(path) || !!t.extras.replaceUrl) {
|
|
4692
|
+
this.location.replaceState(path, '', state);
|
|
4638
4693
|
}
|
|
4639
4694
|
else {
|
|
4640
|
-
this.location.go(path, '',
|
|
4695
|
+
this.location.go(path, '', state);
|
|
4641
4696
|
}
|
|
4642
4697
|
}
|
|
4643
4698
|
resetStateAndUrl(storedState, storedUrl, rawUrl) {
|
|
@@ -4647,7 +4702,43 @@ class Router {
|
|
|
4647
4702
|
this.resetUrlToCurrentUrlTree();
|
|
4648
4703
|
}
|
|
4649
4704
|
resetUrlToCurrentUrlTree() {
|
|
4650
|
-
this.location.replaceState(this.urlSerializer.serialize(this.rawUrlTree), '',
|
|
4705
|
+
this.location.replaceState(this.urlSerializer.serialize(this.rawUrlTree), '', this.generateNgRouterState(this.lastSuccessfulId, this.currentPageId));
|
|
4706
|
+
}
|
|
4707
|
+
/**
|
|
4708
|
+
* Responsible for handling the cancellation of a navigation:
|
|
4709
|
+
* - performs the necessary rollback action to restore the browser URL to the
|
|
4710
|
+
* state before the transition
|
|
4711
|
+
* - triggers the `NavigationCancel` event
|
|
4712
|
+
* - resolves the transition promise with `false`
|
|
4713
|
+
*/
|
|
4714
|
+
cancelNavigationTransition(t, reason) {
|
|
4715
|
+
if (this.canceledNavigationResolution === 'computed') {
|
|
4716
|
+
// The navigator change the location before triggered the browser event,
|
|
4717
|
+
// so we need to go back to the current url if the navigation is canceled.
|
|
4718
|
+
// Also, when navigation gets cancelled while using url update strategy eager, then we need to
|
|
4719
|
+
// go back. Because, when `urlUpdateSrategy` is `eager`; `setBrowserUrl` method is called
|
|
4720
|
+
// before any verification.
|
|
4721
|
+
if (t.source === 'popstate' || this.urlUpdateStrategy === 'eager') {
|
|
4722
|
+
const targetPagePosition = this.currentPageId - t.targetPageId;
|
|
4723
|
+
this.location.historyGo(targetPagePosition);
|
|
4724
|
+
}
|
|
4725
|
+
else {
|
|
4726
|
+
// If update is not 'eager' and the transition navigation source isn't 'popstate', then the
|
|
4727
|
+
// navigation was cancelled before any browser url change so nothing needs to be restored.
|
|
4728
|
+
}
|
|
4729
|
+
}
|
|
4730
|
+
else {
|
|
4731
|
+
this.resetUrlToCurrentUrlTree();
|
|
4732
|
+
}
|
|
4733
|
+
const navCancel = new NavigationCancel(t.id, this.serializeUrl(t.extractedUrl), reason);
|
|
4734
|
+
this.triggerEvent(navCancel);
|
|
4735
|
+
t.resolve(false);
|
|
4736
|
+
}
|
|
4737
|
+
generateNgRouterState(navigationId, routerPageId) {
|
|
4738
|
+
if (this.canceledNavigationResolution === 'computed') {
|
|
4739
|
+
return { navigationId, ɵrouterPageId: routerPageId };
|
|
4740
|
+
}
|
|
4741
|
+
return { navigationId };
|
|
4651
4742
|
}
|
|
4652
4743
|
}
|
|
4653
4744
|
Router.decorators = [
|
|
@@ -5789,11 +5880,16 @@ class RouterInitializer {
|
|
|
5789
5880
|
constructor(injector) {
|
|
5790
5881
|
this.injector = injector;
|
|
5791
5882
|
this.initNavigation = false;
|
|
5883
|
+
this.destroyed = false;
|
|
5792
5884
|
this.resultOfPreactivationDone = new Subject();
|
|
5793
5885
|
}
|
|
5794
5886
|
appInitializer() {
|
|
5795
5887
|
const p = this.injector.get(LOCATION_INITIALIZED, Promise.resolve(null));
|
|
5796
5888
|
return p.then(() => {
|
|
5889
|
+
// If the injector was destroyed, the DI lookups below will fail.
|
|
5890
|
+
if (this.destroyed) {
|
|
5891
|
+
return Promise.resolve(true);
|
|
5892
|
+
}
|
|
5797
5893
|
let resolve = null;
|
|
5798
5894
|
const res = new Promise(r => resolve = r);
|
|
5799
5895
|
const router = this.injector.get(Router);
|
|
@@ -5844,6 +5940,9 @@ class RouterInitializer {
|
|
|
5844
5940
|
this.resultOfPreactivationDone.next(null);
|
|
5845
5941
|
this.resultOfPreactivationDone.complete();
|
|
5846
5942
|
}
|
|
5943
|
+
ngOnDestroy() {
|
|
5944
|
+
this.destroyed = true;
|
|
5945
|
+
}
|
|
5847
5946
|
}
|
|
5848
5947
|
RouterInitializer.decorators = [
|
|
5849
5948
|
{ type: Injectable }
|
|
@@ -5888,7 +5987,7 @@ function provideRouterInitializer() {
|
|
|
5888
5987
|
/**
|
|
5889
5988
|
* @publicApi
|
|
5890
5989
|
*/
|
|
5891
|
-
const VERSION = new Version('12.1.0
|
|
5990
|
+
const VERSION = new Version('12.1.0');
|
|
5892
5991
|
|
|
5893
5992
|
/**
|
|
5894
5993
|
* @license
|