@angular/router 12.1.0-next.5 → 12.1.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/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 +167 -37
- package/bundles/router.umd.js.map +1 -1
- package/esm2015/src/events.js +1 -1
- package/esm2015/src/router.js +142 -30
- package/esm2015/src/router_module.js +9 -1
- package/esm2015/src/router_state.js +1 -1
- package/esm2015/src/version.js +1 -1
- package/fesm2015/router.js +151 -31
- package/fesm2015/router.js.map +1 -1
- package/fesm2015/testing.js +1 -1
- package/fesm2015/upgrade.js +1 -1
- package/package.json +4 -4
- package/router.d.ts +36 -8
- package/router.metadata.json +1 -1
- package/testing/testing.d.ts +4 -4
- package/testing.d.ts +1 -1
- package/upgrade/upgrade.d.ts +1 -1
- package/upgrade.d.ts +1 -1
package/fesm2015/router.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular v12.1.
|
|
2
|
+
* @license Angular v12.1.2
|
|
3
3
|
* (c) 2010-2021 Google LLC. https://angular.io/
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
@@ -3876,6 +3876,15 @@ class Router {
|
|
|
3876
3876
|
*/
|
|
3877
3877
|
this.lastLocationChangeInfo = null;
|
|
3878
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 is used to track what page the router last activated. When an attempted navigation fails,
|
|
3884
|
+
* the router can then use this to compute how to restore the state back to the previously active
|
|
3885
|
+
* page.
|
|
3886
|
+
*/
|
|
3887
|
+
this.currentPageId = 0;
|
|
3879
3888
|
this.isNgZoneEnabled = false;
|
|
3880
3889
|
/**
|
|
3881
3890
|
* An event stream for routing events in this NgModule.
|
|
@@ -3952,6 +3961,24 @@ class Router {
|
|
|
3952
3961
|
* @see `RouterModule`
|
|
3953
3962
|
*/
|
|
3954
3963
|
this.relativeLinkResolution = 'corrected';
|
|
3964
|
+
/**
|
|
3965
|
+
* Configures how the Router attempts to restore state when a navigation is cancelled.
|
|
3966
|
+
*
|
|
3967
|
+
* 'replace' - Always uses `location.replaceState` to set the browser state to the state of the
|
|
3968
|
+
* router before the navigation started.
|
|
3969
|
+
*
|
|
3970
|
+
* 'computed' - Will always return to the same state that corresponds to the actual Angular route
|
|
3971
|
+
* when the navigation gets cancelled right after triggering a `popstate` event.
|
|
3972
|
+
*
|
|
3973
|
+
* The default value is `replace`
|
|
3974
|
+
*
|
|
3975
|
+
* @internal
|
|
3976
|
+
*/
|
|
3977
|
+
// TODO(atscott): Determine how/when/if to make this public API
|
|
3978
|
+
// This shouldn’t be an option at all but may need to be in order to allow migration without a
|
|
3979
|
+
// breaking change. We need to determine if it should be made into public api (or if we forgo
|
|
3980
|
+
// the option and release as a breaking change bug fix in a major version).
|
|
3981
|
+
this.canceledNavigationResolution = 'replace';
|
|
3955
3982
|
const onLoadStart = (r) => this.triggerEvent(new RouteConfigLoadStart(r));
|
|
3956
3983
|
const onLoadEnd = (r) => this.triggerEvent(new RouteConfigLoadEnd(r));
|
|
3957
3984
|
this.ngModule = injector.get(NgModuleRef);
|
|
@@ -3966,6 +3993,7 @@ class Router {
|
|
|
3966
3993
|
this.routerState = createEmptyState(this.currentUrlTree, this.rootComponentType);
|
|
3967
3994
|
this.transitions = new BehaviorSubject({
|
|
3968
3995
|
id: 0,
|
|
3996
|
+
targetPageId: 0,
|
|
3969
3997
|
currentUrlTree: this.currentUrlTree,
|
|
3970
3998
|
currentRawUrl: this.currentUrlTree,
|
|
3971
3999
|
extractedUrl: this.urlHandlingStrategy.extract(this.currentUrlTree),
|
|
@@ -3987,6 +4015,15 @@ class Router {
|
|
|
3987
4015
|
this.navigations = this.setupNavigations(this.transitions);
|
|
3988
4016
|
this.processNavigations();
|
|
3989
4017
|
}
|
|
4018
|
+
/**
|
|
4019
|
+
* The ɵrouterPageId of whatever page is currently active in the browser history. This is
|
|
4020
|
+
* important for computing the target page id for new navigations because we need to ensure each
|
|
4021
|
+
* page id in the browser history is 1 more than the previous entry.
|
|
4022
|
+
*/
|
|
4023
|
+
get browserPageId() {
|
|
4024
|
+
var _a;
|
|
4025
|
+
return (_a = this.location.getState()) === null || _a === void 0 ? void 0 : _a.ɵrouterPageId;
|
|
4026
|
+
}
|
|
3990
4027
|
setupNavigations(transitions) {
|
|
3991
4028
|
const eventsSubject = this.events;
|
|
3992
4029
|
return transitions.pipe(filter(t => t.id !== 0),
|
|
@@ -4038,7 +4075,7 @@ class Router {
|
|
|
4038
4075
|
tap(t => {
|
|
4039
4076
|
if (this.urlUpdateStrategy === 'eager') {
|
|
4040
4077
|
if (!t.extras.skipLocationChange) {
|
|
4041
|
-
this.setBrowserUrl(t.urlAfterRedirects,
|
|
4078
|
+
this.setBrowserUrl(t.urlAfterRedirects, t);
|
|
4042
4079
|
}
|
|
4043
4080
|
this.browserUrlTree = t.urlAfterRedirects;
|
|
4044
4081
|
}
|
|
@@ -4098,10 +4135,7 @@ class Router {
|
|
|
4098
4135
|
this.triggerEvent(guardsEnd);
|
|
4099
4136
|
}), filter(t => {
|
|
4100
4137
|
if (!t.guardsResult) {
|
|
4101
|
-
this.
|
|
4102
|
-
const navCancel = new NavigationCancel(t.id, this.serializeUrl(t.extractedUrl), '');
|
|
4103
|
-
eventsSubject.next(navCancel);
|
|
4104
|
-
t.resolve(false);
|
|
4138
|
+
this.cancelNavigationTransitionRestoreHistory(t, '');
|
|
4105
4139
|
return false;
|
|
4106
4140
|
}
|
|
4107
4141
|
return true;
|
|
@@ -4118,9 +4152,7 @@ class Router {
|
|
|
4118
4152
|
next: () => dataResolved = true,
|
|
4119
4153
|
complete: () => {
|
|
4120
4154
|
if (!dataResolved) {
|
|
4121
|
-
|
|
4122
|
-
eventsSubject.next(navCancel);
|
|
4123
|
-
t.resolve(false);
|
|
4155
|
+
this.cancelNavigationTransitionRestoreHistory(t, `At least one route resolver didn't emit any value.`);
|
|
4124
4156
|
}
|
|
4125
4157
|
}
|
|
4126
4158
|
}));
|
|
@@ -4157,7 +4189,7 @@ class Router {
|
|
|
4157
4189
|
this.routerState = t.targetRouterState;
|
|
4158
4190
|
if (this.urlUpdateStrategy === 'deferred') {
|
|
4159
4191
|
if (!t.extras.skipLocationChange) {
|
|
4160
|
-
this.setBrowserUrl(this.rawUrlTree,
|
|
4192
|
+
this.setBrowserUrl(this.rawUrlTree, t);
|
|
4161
4193
|
}
|
|
4162
4194
|
this.browserUrlTree = t.urlAfterRedirects;
|
|
4163
4195
|
}
|
|
@@ -4177,17 +4209,28 @@ class Router {
|
|
|
4177
4209
|
* event is fired when a navigation gets cancelled but not caught by other
|
|
4178
4210
|
* means. */
|
|
4179
4211
|
if (!completed && !errored) {
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4212
|
+
const cancelationReason = `Navigation ID ${t.id} is not equal to the current navigation id ${this.navigationId}`;
|
|
4213
|
+
if (this.canceledNavigationResolution === 'replace') {
|
|
4214
|
+
// Must reset to current URL tree here to ensure history.state is set. On
|
|
4215
|
+
// a fresh page load, if a new navigation comes in before a successful
|
|
4216
|
+
// navigation completes, there will be nothing in
|
|
4217
|
+
// history.state.navigationId. This can cause sync problems with
|
|
4218
|
+
// AngularJS sync code which looks for a value here in order to determine
|
|
4219
|
+
// whether or not to handle a given popstate event or to leave it to the
|
|
4220
|
+
// Angular router.
|
|
4221
|
+
this.cancelNavigationTransitionRestoreHistory(t, cancelationReason);
|
|
4222
|
+
}
|
|
4223
|
+
else {
|
|
4224
|
+
// We cannot trigger a `location.historyGo` if the
|
|
4225
|
+
// cancellation was due to a new navigation before the previous could
|
|
4226
|
+
// complete. This is because `location.historyGo` triggers a `popstate`
|
|
4227
|
+
// which would also trigger another navigation. Instead, treat this as a
|
|
4228
|
+
// redirect and do not reset the state.
|
|
4229
|
+
this.cancelNavigationTransition(t, cancelationReason);
|
|
4230
|
+
// TODO(atscott): The same problem happens here with a fresh page load
|
|
4231
|
+
// and a new navigation before that completes where we won't set a page
|
|
4232
|
+
// id.
|
|
4233
|
+
}
|
|
4191
4234
|
}
|
|
4192
4235
|
// currentNavigation should always be reset to null here. If navigation was
|
|
4193
4236
|
// successful, lastSuccessfulTransition will have already been set. Therefore
|
|
@@ -4290,15 +4333,16 @@ class Router {
|
|
|
4290
4333
|
if (!this.locationSubscription) {
|
|
4291
4334
|
this.locationSubscription = this.location.subscribe(event => {
|
|
4292
4335
|
const currentChange = this.extractLocationChangeInfoFromEvent(event);
|
|
4336
|
+
// The `setTimeout` was added in #12160 and is likely to support Angular/AngularJS
|
|
4337
|
+
// hybrid apps.
|
|
4293
4338
|
if (this.shouldScheduleNavigation(this.lastLocationChangeInfo, currentChange)) {
|
|
4294
|
-
// The `setTimeout` was added in #12160 and is likely to support Angular/AngularJS
|
|
4295
|
-
// hybrid apps.
|
|
4296
4339
|
setTimeout(() => {
|
|
4297
4340
|
const { source, state, urlTree } = currentChange;
|
|
4298
4341
|
const extras = { replaceUrl: true };
|
|
4299
4342
|
if (state) {
|
|
4300
4343
|
const stateCopy = Object.assign({}, state);
|
|
4301
4344
|
delete stateCopy.navigationId;
|
|
4345
|
+
delete stateCopy.ɵrouterPageId;
|
|
4302
4346
|
if (Object.keys(stateCopy).length !== 0) {
|
|
4303
4347
|
extras.state = stateCopy;
|
|
4304
4348
|
}
|
|
@@ -4574,6 +4618,7 @@ class Router {
|
|
|
4574
4618
|
this.navigations.subscribe(t => {
|
|
4575
4619
|
this.navigated = true;
|
|
4576
4620
|
this.lastSuccessfulId = t.id;
|
|
4621
|
+
this.currentPageId = t.targetPageId;
|
|
4577
4622
|
this.events
|
|
4578
4623
|
.next(new NavigationEnd(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(this.currentUrlTree)));
|
|
4579
4624
|
this.lastSuccessfulNavigation = this.currentNavigation;
|
|
@@ -4583,6 +4628,7 @@ class Router {
|
|
|
4583
4628
|
});
|
|
4584
4629
|
}
|
|
4585
4630
|
scheduleNavigation(rawUrl, source, restoredState, extras, priorPromise) {
|
|
4631
|
+
var _a, _b;
|
|
4586
4632
|
if (this.disposed) {
|
|
4587
4633
|
return Promise.resolve(false);
|
|
4588
4634
|
}
|
|
@@ -4624,8 +4670,36 @@ class Router {
|
|
|
4624
4670
|
});
|
|
4625
4671
|
}
|
|
4626
4672
|
const id = ++this.navigationId;
|
|
4673
|
+
let targetPageId;
|
|
4674
|
+
if (this.canceledNavigationResolution === 'computed') {
|
|
4675
|
+
const isInitialPage = this.currentPageId === 0;
|
|
4676
|
+
if (isInitialPage) {
|
|
4677
|
+
restoredState = this.location.getState();
|
|
4678
|
+
}
|
|
4679
|
+
// If the `ɵrouterPageId` exist in the state then `targetpageId` should have the value of
|
|
4680
|
+
// `ɵrouterPageId`. This is the case for something like a page refresh where we assign the
|
|
4681
|
+
// target id to the previously set value for that page.
|
|
4682
|
+
if (restoredState && restoredState.ɵrouterPageId) {
|
|
4683
|
+
targetPageId = restoredState.ɵrouterPageId;
|
|
4684
|
+
}
|
|
4685
|
+
else {
|
|
4686
|
+
// If we're replacing the URL or doing a silent navigation, we do not want to increment the
|
|
4687
|
+
// page id because we aren't pushing a new entry to history.
|
|
4688
|
+
if (extras.replaceUrl || extras.skipLocationChange) {
|
|
4689
|
+
targetPageId = (_a = this.browserPageId) !== null && _a !== void 0 ? _a : 0;
|
|
4690
|
+
}
|
|
4691
|
+
else {
|
|
4692
|
+
targetPageId = ((_b = this.browserPageId) !== null && _b !== void 0 ? _b : 0) + 1;
|
|
4693
|
+
}
|
|
4694
|
+
}
|
|
4695
|
+
}
|
|
4696
|
+
else {
|
|
4697
|
+
// This is unused when `canceledNavigationResolution` is not computed.
|
|
4698
|
+
targetPageId = 0;
|
|
4699
|
+
}
|
|
4627
4700
|
this.setTransition({
|
|
4628
4701
|
id,
|
|
4702
|
+
targetPageId,
|
|
4629
4703
|
source,
|
|
4630
4704
|
restoredState,
|
|
4631
4705
|
currentUrlTree: this.currentUrlTree,
|
|
@@ -4644,15 +4718,14 @@ class Router {
|
|
|
4644
4718
|
return Promise.reject(e);
|
|
4645
4719
|
});
|
|
4646
4720
|
}
|
|
4647
|
-
setBrowserUrl(url,
|
|
4721
|
+
setBrowserUrl(url, t) {
|
|
4648
4722
|
const path = this.urlSerializer.serialize(url);
|
|
4649
|
-
state = state
|
|
4650
|
-
if (this.location.isCurrentPathEqualTo(path) || replaceUrl) {
|
|
4651
|
-
|
|
4652
|
-
this.location.replaceState(path, '', Object.assign(Object.assign({}, state), { navigationId: id }));
|
|
4723
|
+
const state = Object.assign(Object.assign({}, t.extras.state), this.generateNgRouterState(t.id, t.targetPageId));
|
|
4724
|
+
if (this.location.isCurrentPathEqualTo(path) || !!t.extras.replaceUrl) {
|
|
4725
|
+
this.location.replaceState(path, '', state);
|
|
4653
4726
|
}
|
|
4654
4727
|
else {
|
|
4655
|
-
this.location.go(path, '',
|
|
4728
|
+
this.location.go(path, '', state);
|
|
4656
4729
|
}
|
|
4657
4730
|
}
|
|
4658
4731
|
resetStateAndUrl(storedState, storedUrl, rawUrl) {
|
|
@@ -4662,7 +4735,46 @@ class Router {
|
|
|
4662
4735
|
this.resetUrlToCurrentUrlTree();
|
|
4663
4736
|
}
|
|
4664
4737
|
resetUrlToCurrentUrlTree() {
|
|
4665
|
-
this.location.replaceState(this.urlSerializer.serialize(this.rawUrlTree), '',
|
|
4738
|
+
this.location.replaceState(this.urlSerializer.serialize(this.rawUrlTree), '', this.generateNgRouterState(this.lastSuccessfulId, this.currentPageId));
|
|
4739
|
+
}
|
|
4740
|
+
/**
|
|
4741
|
+
* Responsible for handling the cancellation of a navigation:
|
|
4742
|
+
* - performs the necessary rollback action to restore the browser URL to the
|
|
4743
|
+
* state before the transition
|
|
4744
|
+
* - triggers the `NavigationCancel` event
|
|
4745
|
+
* - resolves the transition promise with `false`
|
|
4746
|
+
*/
|
|
4747
|
+
cancelNavigationTransitionRestoreHistory(t, reason) {
|
|
4748
|
+
if (this.canceledNavigationResolution === 'computed') {
|
|
4749
|
+
// The navigator change the location before triggered the browser event,
|
|
4750
|
+
// so we need to go back to the current url if the navigation is canceled.
|
|
4751
|
+
// Also, when navigation gets cancelled while using url update strategy eager, then we need to
|
|
4752
|
+
// go back. Because, when `urlUpdateSrategy` is `eager`; `setBrowserUrl` method is called
|
|
4753
|
+
// before any verification.
|
|
4754
|
+
if (t.source === 'popstate' || this.urlUpdateStrategy === 'eager') {
|
|
4755
|
+
const targetPagePosition = this.currentPageId - t.targetPageId;
|
|
4756
|
+
this.location.historyGo(targetPagePosition);
|
|
4757
|
+
}
|
|
4758
|
+
else {
|
|
4759
|
+
// If update is not 'eager' and the transition navigation source isn't 'popstate', then the
|
|
4760
|
+
// navigation was cancelled before any browser url change so nothing needs to be restored.
|
|
4761
|
+
}
|
|
4762
|
+
}
|
|
4763
|
+
else {
|
|
4764
|
+
this.resetUrlToCurrentUrlTree();
|
|
4765
|
+
}
|
|
4766
|
+
this.cancelNavigationTransition(t, reason);
|
|
4767
|
+
}
|
|
4768
|
+
cancelNavigationTransition(t, reason) {
|
|
4769
|
+
const navCancel = new NavigationCancel(t.id, this.serializeUrl(t.extractedUrl), reason);
|
|
4770
|
+
this.triggerEvent(navCancel);
|
|
4771
|
+
t.resolve(false);
|
|
4772
|
+
}
|
|
4773
|
+
generateNgRouterState(navigationId, routerPageId) {
|
|
4774
|
+
if (this.canceledNavigationResolution === 'computed') {
|
|
4775
|
+
return { navigationId, ɵrouterPageId: routerPageId };
|
|
4776
|
+
}
|
|
4777
|
+
return { navigationId };
|
|
4666
4778
|
}
|
|
4667
4779
|
}
|
|
4668
4780
|
Router.decorators = [
|
|
@@ -5804,11 +5916,16 @@ class RouterInitializer {
|
|
|
5804
5916
|
constructor(injector) {
|
|
5805
5917
|
this.injector = injector;
|
|
5806
5918
|
this.initNavigation = false;
|
|
5919
|
+
this.destroyed = false;
|
|
5807
5920
|
this.resultOfPreactivationDone = new Subject();
|
|
5808
5921
|
}
|
|
5809
5922
|
appInitializer() {
|
|
5810
5923
|
const p = this.injector.get(LOCATION_INITIALIZED, Promise.resolve(null));
|
|
5811
5924
|
return p.then(() => {
|
|
5925
|
+
// If the injector was destroyed, the DI lookups below will fail.
|
|
5926
|
+
if (this.destroyed) {
|
|
5927
|
+
return Promise.resolve(true);
|
|
5928
|
+
}
|
|
5812
5929
|
let resolve = null;
|
|
5813
5930
|
const res = new Promise(r => resolve = r);
|
|
5814
5931
|
const router = this.injector.get(Router);
|
|
@@ -5859,6 +5976,9 @@ class RouterInitializer {
|
|
|
5859
5976
|
this.resultOfPreactivationDone.next(null);
|
|
5860
5977
|
this.resultOfPreactivationDone.complete();
|
|
5861
5978
|
}
|
|
5979
|
+
ngOnDestroy() {
|
|
5980
|
+
this.destroyed = true;
|
|
5981
|
+
}
|
|
5862
5982
|
}
|
|
5863
5983
|
RouterInitializer.decorators = [
|
|
5864
5984
|
{ type: Injectable }
|
|
@@ -5903,7 +6023,7 @@ function provideRouterInitializer() {
|
|
|
5903
6023
|
/**
|
|
5904
6024
|
* @publicApi
|
|
5905
6025
|
*/
|
|
5906
|
-
const VERSION = new Version('12.1.
|
|
6026
|
+
const VERSION = new Version('12.1.2');
|
|
5907
6027
|
|
|
5908
6028
|
/**
|
|
5909
6029
|
* @license
|