@angular/router 12.0.1 → 12.0.5

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.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v12.0.1
2
+ * @license Angular v12.0.5
3
3
  * (c) 2010-2021 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v12.0.1
2
+ * @license Angular v12.0.5
3
3
  * (c) 2010-2021 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v12.0.1
2
+ * @license Angular v12.0.5
3
3
  * (c) 2010-2021 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
@@ -421,7 +421,7 @@
421
421
  }(RouterEvent));
422
422
  /**
423
423
  * An event triggered when a navigation is canceled, directly or indirectly.
424
- * This can happen when a route guard
424
+ * This can happen for several reasons including when a route guard
425
425
  * returns `false` or initiates a redirect by returning a `UrlTree`.
426
426
  *
427
427
  * @see `NavigationStart`
@@ -1339,12 +1339,14 @@
1339
1339
  .join('');
1340
1340
  }
1341
1341
  function serializeQueryParams(params) {
1342
- var strParams = Object.keys(params).map(function (name) {
1342
+ var strParams = Object.keys(params)
1343
+ .map(function (name) {
1343
1344
  var value = params[name];
1344
1345
  return Array.isArray(value) ?
1345
1346
  value.map(function (v) { return encodeUriQuery(name) + "=" + encodeUriQuery(v); }).join('&') :
1346
1347
  encodeUriQuery(name) + "=" + encodeUriQuery(value);
1347
- });
1348
+ })
1349
+ .filter(function (s) { return !!s; });
1348
1350
  return strParams.length ? "?" + strParams.join('&') : '';
1349
1351
  }
1350
1352
  var SEGMENT_RE = /^[^\/()?;=#]+/;
@@ -1723,6 +1725,10 @@
1723
1725
  * The following example shows how to construct a component using information from a
1724
1726
  * currently activated route.
1725
1727
  *
1728
+ * Note: the observables in this class only emit when the current and previous values differ based
1729
+ * on shallow equality. For example, changing deeply nested properties in resolved `data` will not
1730
+ * cause the `ActivatedRoute.data` `Observable` to emit a new value.
1731
+ *
1726
1732
  * {@example router/activated-route/module.ts region="activated-route"
1727
1733
  * header="activated-route.component.ts"}
1728
1734
  *
@@ -3083,7 +3089,8 @@
3083
3089
  }));
3084
3090
  return urlTrees$.pipe(operators.catchError(function (e) {
3085
3091
  if (e instanceof AbsoluteRedirect) {
3086
- // after an absolute redirect we do not apply any more redirects!
3092
+ // After an absolute redirect we do not apply any more redirects!
3093
+ // If this implementation changes, update the documentation note in `redirectTo`.
3087
3094
  _this.allowRedirects = false;
3088
3095
  // we need to run matching, so we can fetch all lazy-loaded modules
3089
3096
  return _this.match(e.urlTree);
@@ -4208,7 +4215,12 @@
4208
4215
  */
4209
4216
  /**
4210
4217
  * The [DI token](guide/glossary/#di-token) for a router configuration.
4211
- * @see `ROUTES`
4218
+ *
4219
+ * `ROUTES` is a low level API for router configuration via dependency injection.
4220
+ *
4221
+ * We recommend that in almost all cases to use higher level APIs such as `RouterModule.forRoot()`,
4222
+ * `RouterModule.forChild()`, `provideRoutes`, or `Router.resetConfig()`.
4223
+ *
4212
4224
  * @publicApi
4213
4225
  */
4214
4226
  var ROUTES = new core.InjectionToken('ROUTES');
@@ -4451,6 +4463,11 @@
4451
4463
  */
4452
4464
  this.lastLocationChangeInfo = null;
4453
4465
  this.navigationId = 0;
4466
+ /**
4467
+ * The id of the currently active page in the router.
4468
+ * Updated to the transition's target id on a successful navigation.
4469
+ */
4470
+ this.currentPageId = 0;
4454
4471
  this.isNgZoneEnabled = false;
4455
4472
  /**
4456
4473
  * An event stream for routing events in this NgModule.
@@ -4492,8 +4509,16 @@
4492
4509
  this.routeReuseStrategy = new DefaultRouteReuseStrategy();
4493
4510
  /**
4494
4511
  * How to handle a navigation request to the current URL. One of:
4512
+ *
4495
4513
  * - `'ignore'` : The router ignores the request.
4496
4514
  * - `'reload'` : The router reloads the URL. Use to implement a "refresh" feature.
4515
+ *
4516
+ * Note that this only configures whether the Route reprocesses the URL and triggers related
4517
+ * action and events like redirects, guards, and resolvers. By default, the router re-uses a
4518
+ * component instance when it re-navigates to the same component type without visiting a different
4519
+ * component first. This behavior is configured by the `RouteReuseStrategy`. In order to reload
4520
+ * routed components on same url navigation, you need to set `onSameUrlNavigation` to `'reload'`
4521
+ * _and_ provide a `RouteReuseStrategy` which returns `false` for `shouldReuseRoute`.
4497
4522
  */
4498
4523
  this.onSameUrlNavigation = 'ignore';
4499
4524
  /**
@@ -4519,6 +4544,24 @@
4519
4544
  * @see `RouterModule`
4520
4545
  */
4521
4546
  this.relativeLinkResolution = 'corrected';
4547
+ /**
4548
+ * Configures how the Router attempts to restore state when a navigation is cancelled.
4549
+ *
4550
+ * 'replace' - Always uses `location.replaceState` to set the browser state to the state of the
4551
+ * router before the navigation started.
4552
+ *
4553
+ * 'computed' - Will always return to the same state that corresponds to the actual Angular route
4554
+ * when the navigation gets cancelled right after triggering a `popstate` event.
4555
+ *
4556
+ * The default value is `replace`
4557
+ *
4558
+ * @internal
4559
+ */
4560
+ // TODO(atscott): Determine how/when/if to make this public API
4561
+ // This shouldn’t be an option at all but may need to be in order to allow migration without a
4562
+ // breaking change. We need to determine if it should be made into public api (or if we forgo
4563
+ // the option and release as a breaking change bug fix in a major version).
4564
+ this.canceledNavigationResolution = 'replace';
4522
4565
  var onLoadStart = function (r) { return _this.triggerEvent(new RouteConfigLoadStart(r)); };
4523
4566
  var onLoadEnd = function (r) { return _this.triggerEvent(new RouteConfigLoadEnd(r)); };
4524
4567
  this.ngModule = injector.get(core.NgModuleRef);
@@ -4533,6 +4576,7 @@
4533
4576
  this.routerState = createEmptyState(this.currentUrlTree, this.rootComponentType);
4534
4577
  this.transitions = new rxjs.BehaviorSubject({
4535
4578
  id: 0,
4579
+ targetPageId: 0,
4536
4580
  currentUrlTree: this.currentUrlTree,
4537
4581
  currentRawUrl: this.currentUrlTree,
4538
4582
  extractedUrl: this.urlHandlingStrategy.extract(this.currentUrlTree),
@@ -4606,7 +4650,7 @@
4606
4650
  operators.tap(function (t) {
4607
4651
  if (_this.urlUpdateStrategy === 'eager') {
4608
4652
  if (!t.extras.skipLocationChange) {
4609
- _this.setBrowserUrl(t.urlAfterRedirects, !!t.extras.replaceUrl, t.id, t.extras.state);
4653
+ _this.setBrowserUrl(t.urlAfterRedirects, t);
4610
4654
  }
4611
4655
  _this.browserUrlTree = t.urlAfterRedirects;
4612
4656
  }
@@ -4666,10 +4710,7 @@
4666
4710
  _this.triggerEvent(guardsEnd);
4667
4711
  }), operators.filter(function (t) {
4668
4712
  if (!t.guardsResult) {
4669
- _this.resetUrlToCurrentUrlTree();
4670
- var navCancel = new NavigationCancel(t.id, _this.serializeUrl(t.extractedUrl), '');
4671
- eventsSubject.next(navCancel);
4672
- t.resolve(false);
4713
+ _this.cancelNavigationTransition(t, '');
4673
4714
  return false;
4674
4715
  }
4675
4716
  return true;
@@ -4686,9 +4727,7 @@
4686
4727
  next: function () { return dataResolved = true; },
4687
4728
  complete: function () {
4688
4729
  if (!dataResolved) {
4689
- var navCancel = new NavigationCancel(t.id, _this.serializeUrl(t.extractedUrl), "At least one route resolver didn't emit any value.");
4690
- eventsSubject.next(navCancel);
4691
- t.resolve(false);
4730
+ _this.cancelNavigationTransition(t, "At least one route resolver didn't emit any value.");
4692
4731
  }
4693
4732
  }
4694
4733
  }));
@@ -4725,7 +4764,7 @@
4725
4764
  _this.routerState = t.targetRouterState;
4726
4765
  if (_this.urlUpdateStrategy === 'deferred') {
4727
4766
  if (!t.extras.skipLocationChange) {
4728
- _this.setBrowserUrl(_this.rawUrlTree, !!t.extras.replaceUrl, t.id, t.extras.state);
4767
+ _this.setBrowserUrl(_this.rawUrlTree, t);
4729
4768
  }
4730
4769
  _this.browserUrlTree = t.urlAfterRedirects;
4731
4770
  }
@@ -4752,10 +4791,7 @@
4752
4791
  // sync code which looks for a value here in order to determine whether or
4753
4792
  // not to handle a given popstate event or to leave it to the Angular
4754
4793
  // router.
4755
- _this.resetUrlToCurrentUrlTree();
4756
- var navCancel = new NavigationCancel(t.id, _this.serializeUrl(t.extractedUrl), "Navigation ID " + t.id + " is not equal to the current navigation id " + _this.navigationId);
4757
- eventsSubject.next(navCancel);
4758
- t.resolve(false);
4794
+ _this.cancelNavigationTransition(t, "Navigation ID " + t.id + " is not equal to the current navigation id " + _this.navigationId);
4759
4795
  }
4760
4796
  // currentNavigation should always be reset to null here. If navigation was
4761
4797
  // successful, lastSuccessfulTransition will have already been set. Therefore
@@ -4868,6 +4904,7 @@
4868
4904
  if (state) {
4869
4905
  var stateCopy = Object.assign({}, state);
4870
4906
  delete stateCopy.navigationId;
4907
+ delete stateCopy.ɵrouterPageId;
4871
4908
  if (Object.keys(stateCopy).length !== 0) {
4872
4909
  extras.state = stateCopy;
4873
4910
  }
@@ -5068,7 +5105,14 @@
5068
5105
  }
5069
5106
  var urlTree = isUrlTree(url) ? url : this.parseUrl(url);
5070
5107
  var mergedTree = this.urlHandlingStrategy.merge(urlTree, this.rawUrlTree);
5071
- return this.scheduleNavigation(mergedTree, 'imperative', null, extras);
5108
+ var restoredState = null;
5109
+ if (this.canceledNavigationResolution === 'computed') {
5110
+ var isInitialPage = this.currentPageId === 0;
5111
+ if (isInitialPage || extras.skipLocationChange || extras.replaceUrl) {
5112
+ restoredState = this.location.getState();
5113
+ }
5114
+ }
5115
+ return this.scheduleNavigation(mergedTree, 'imperative', restoredState, extras);
5072
5116
  };
5073
5117
  /**
5074
5118
  * Navigate based on the provided array of commands and a starting point.
@@ -5151,6 +5195,7 @@
5151
5195
  this.navigations.subscribe(function (t) {
5152
5196
  _this.navigated = true;
5153
5197
  _this.lastSuccessfulId = t.id;
5198
+ _this.currentPageId = t.targetPageId;
5154
5199
  _this.events
5155
5200
  .next(new NavigationEnd(t.id, _this.serializeUrl(t.extractedUrl), _this.serializeUrl(_this.currentUrlTree)));
5156
5201
  _this.lastSuccessfulNavigation = _this.currentNavigation;
@@ -5201,8 +5246,24 @@
5201
5246
  });
5202
5247
  }
5203
5248
  var id = ++this.navigationId;
5249
+ var targetPageId;
5250
+ if (this.canceledNavigationResolution === 'computed') {
5251
+ // If the `ɵrouterPageId` exist in the state then `targetpageId` should have the value of
5252
+ // `ɵrouterPageId`
5253
+ if (restoredState && restoredState.ɵrouterPageId) {
5254
+ targetPageId = restoredState.ɵrouterPageId;
5255
+ }
5256
+ else {
5257
+ targetPageId = this.currentPageId + 1;
5258
+ }
5259
+ }
5260
+ else {
5261
+ // This is unused when `canceledNavigationResolution` is not computed.
5262
+ targetPageId = 0;
5263
+ }
5204
5264
  this.setTransition({
5205
5265
  id: id,
5266
+ targetPageId: targetPageId,
5206
5267
  source: source,
5207
5268
  restoredState: restoredState,
5208
5269
  currentUrlTree: this.currentUrlTree,
@@ -5221,15 +5282,14 @@
5221
5282
  return Promise.reject(e);
5222
5283
  });
5223
5284
  };
5224
- Router.prototype.setBrowserUrl = function (url, replaceUrl, id, state) {
5285
+ Router.prototype.setBrowserUrl = function (url, t) {
5225
5286
  var path = this.urlSerializer.serialize(url);
5226
- state = state || {};
5227
- if (this.location.isCurrentPathEqualTo(path) || replaceUrl) {
5228
- // TODO(jasonaden): Remove first `navigationId` and rely on `ng` namespace.
5229
- this.location.replaceState(path, '', Object.assign(Object.assign({}, state), { navigationId: id }));
5287
+ var state = Object.assign(Object.assign({}, t.extras.state), this.generateNgRouterState(t.id, t.targetPageId));
5288
+ if (this.location.isCurrentPathEqualTo(path) || !!t.extras.replaceUrl) {
5289
+ this.location.replaceState(path, '', state);
5230
5290
  }
5231
5291
  else {
5232
- this.location.go(path, '', Object.assign(Object.assign({}, state), { navigationId: id }));
5292
+ this.location.go(path, '', state);
5233
5293
  }
5234
5294
  };
5235
5295
  Router.prototype.resetStateAndUrl = function (storedState, storedUrl, rawUrl) {
@@ -5239,7 +5299,43 @@
5239
5299
  this.resetUrlToCurrentUrlTree();
5240
5300
  };
5241
5301
  Router.prototype.resetUrlToCurrentUrlTree = function () {
5242
- this.location.replaceState(this.urlSerializer.serialize(this.rawUrlTree), '', { navigationId: this.lastSuccessfulId });
5302
+ this.location.replaceState(this.urlSerializer.serialize(this.rawUrlTree), '', this.generateNgRouterState(this.lastSuccessfulId, this.currentPageId));
5303
+ };
5304
+ /**
5305
+ * Responsible for handling the cancellation of a navigation:
5306
+ * - performs the necessary rollback action to restore the browser URL to the
5307
+ * state before the transition
5308
+ * - triggers the `NavigationCancel` event
5309
+ * - resolves the transition promise with `false`
5310
+ */
5311
+ Router.prototype.cancelNavigationTransition = function (t, reason) {
5312
+ if (this.canceledNavigationResolution === 'computed') {
5313
+ // The navigator change the location before triggered the browser event,
5314
+ // so we need to go back to the current url if the navigation is canceled.
5315
+ // Also, when navigation gets cancelled while using url update strategy eager, then we need to
5316
+ // go back. Because, when `urlUpdateSrategy` is `eager`; `setBrowserUrl` method is called
5317
+ // before any verification.
5318
+ if (t.source === 'popstate' || this.urlUpdateStrategy === 'eager') {
5319
+ var targetPagePosition = this.currentPageId - t.targetPageId;
5320
+ this.location.historyGo(targetPagePosition);
5321
+ }
5322
+ else {
5323
+ // If update is not 'eager' and the transition navigation source isn't 'popstate', then the
5324
+ // navigation was cancelled before any browser url change so nothing needs to be restored.
5325
+ }
5326
+ }
5327
+ else {
5328
+ this.resetUrlToCurrentUrlTree();
5329
+ }
5330
+ var navCancel = new NavigationCancel(t.id, this.serializeUrl(t.extractedUrl), reason);
5331
+ this.triggerEvent(navCancel);
5332
+ t.resolve(false);
5333
+ };
5334
+ Router.prototype.generateNgRouterState = function (navigationId, routerPageId) {
5335
+ if (this.canceledNavigationResolution === 'computed') {
5336
+ return { navigationId: navigationId, ɵrouterPageId: routerPageId };
5337
+ }
5338
+ return { navigationId: navigationId };
5243
5339
  };
5244
5340
  return Router;
5245
5341
  }());
@@ -6545,7 +6641,7 @@
6545
6641
  /**
6546
6642
  * @publicApi
6547
6643
  */
6548
- var VERSION = new core.Version('12.0.1');
6644
+ var VERSION = new core.Version('12.0.5');
6549
6645
 
6550
6646
  /**
6551
6647
  * @license