@angular/router 21.1.2 → 21.2.0-next.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.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v21.1.2
2
+ * @license Angular v21.2.0-next.0
3
3
  * (c) 2010-2026 Google LLC. https://angular.dev/
4
4
  * License: MIT
5
5
  */
@@ -7,11 +7,71 @@
7
7
  import * as i3 from '@angular/common';
8
8
  import { ViewportScroller, PlatformNavigation, PlatformLocation, ɵPRECOMMIT_HANDLER_SUPPORTED as _PRECOMMIT_HANDLER_SUPPORTED, Location, ɵNavigationAdapterForLocation as _NavigationAdapterForLocation, LOCATION_INITIALIZED, LocationStrategy, HashLocationStrategy, PathLocationStrategy } from '@angular/common';
9
9
  import * as i0 from '@angular/core';
10
- import { signal, untracked, inject, ɵINTERNAL_APPLICATION_ERROR_HANDLER as _INTERNAL_APPLICATION_ERROR_HANDLER, HostAttributeToken, ɵRuntimeError as _RuntimeError, booleanAttribute, Directive, Attribute, HostBinding, Input, HostListener, EventEmitter, ContentChildren, Output, Injectable, createEnvironmentInjector, InjectionToken, NgZone, EnvironmentInjector, DestroyRef, afterNextRender, ɵpromiseWithResolvers as _promiseWithResolvers, ɵpublishExternalGlobalUtil as _publishExternalGlobalUtil, makeEnvironmentProviders, APP_BOOTSTRAP_LISTENER, provideEnvironmentInitializer, Injector, ApplicationRef, ɵIS_ENABLED_BLOCKING_INITIAL_NAVIGATION as _IS_ENABLED_BLOCKING_INITIAL_NAVIGATION, provideAppInitializer, ɵperformanceMarkFeature as _performanceMarkFeature, ENVIRONMENT_INITIALIZER, NgModule } from '@angular/core';
11
- import { ROUTER_CONFIGURATION, NavigationEnd, isUrlTree, Router, ActivatedRoute, isActive, exactMatchOptions, subsetMatchOptions, RouterConfigLoader, IMPERATIVE_NAVIGATION, UrlSerializer, NavigationTransitions, NavigationStart, NavigationSkipped, NavigationSkippedCode, Scroll, StateManager, RoutesRecognized, BeforeActivateRoutes, NavigationCancel, NavigationError, isRedirectingEvent, NavigationCancellationCode, ROUTES, afterNextNavigation, ROUTE_INJECTOR_CLEANUP, routeInjectorCleanup, stringifyEvent, NAVIGATION_ERROR_HANDLER, RoutedComponentInputBinder, INPUT_BINDER, CREATE_VIEW_TRANSITION, createViewTransition, VIEW_TRANSITION_OPTIONS, DefaultUrlSerializer, ChildrenOutletContexts, RouterOutlet, ɵEmptyOutletComponent as _EmptyOutletComponent } from './_router-chunk.mjs';
10
+ import { inject, signal, Injectable, HostAttributeToken, linkedSignal, untracked, ɵINTERNAL_APPLICATION_ERROR_HANDLER as _INTERNAL_APPLICATION_ERROR_HANDLER, effect, ɵRuntimeError as _RuntimeError, computed, booleanAttribute, Directive, Attribute, Input, HostListener, EventEmitter, ContentChildren, Output, createEnvironmentInjector, InjectionToken, NgZone, EnvironmentInjector, DestroyRef, afterNextRender, ɵpromiseWithResolvers as _promiseWithResolvers, ɵpublishExternalGlobalUtil as _publishExternalGlobalUtil, makeEnvironmentProviders, APP_BOOTSTRAP_LISTENER, provideEnvironmentInitializer, Injector, ApplicationRef, ɵIS_ENABLED_BLOCKING_INITIAL_NAVIGATION as _IS_ENABLED_BLOCKING_INITIAL_NAVIGATION, provideAppInitializer, ɵperformanceMarkFeature as _performanceMarkFeature, ENVIRONMENT_INITIALIZER, NgModule } from '@angular/core';
11
+ import { Router, StateManager, UrlSerializer, NavigationEnd, UrlTree, ROUTER_CONFIGURATION, isUrlTree, ActivatedRoute, isActive, exactMatchOptions, subsetMatchOptions, RouterConfigLoader, IMPERATIVE_NAVIGATION, NavigationTransitions, NavigationStart, NavigationSkipped, NavigationSkippedCode, Scroll, BeforeRoutesRecognized, BeforeActivateRoutes, NavigationCancel, NavigationError, isRedirectingEvent, NavigationCancellationCode, ROUTES, afterNextNavigation, ROUTE_INJECTOR_CLEANUP, routeInjectorCleanup, stringifyEvent, NAVIGATION_ERROR_HANDLER, RoutedComponentInputBinder, INPUT_BINDER, CREATE_VIEW_TRANSITION, createViewTransition, VIEW_TRANSITION_OPTIONS, DefaultUrlSerializer, ChildrenOutletContexts, RouterOutlet, ɵEmptyOutletComponent as _EmptyOutletComponent } from './_router-chunk.mjs';
12
12
  import { Subject, of, from } from 'rxjs';
13
13
  import { mergeAll, catchError, filter, concatMap, mergeMap } from 'rxjs/operators';
14
14
 
15
+ class ReactiveRouterState {
16
+ router = inject(Router);
17
+ stateManager = inject(StateManager);
18
+ fragment = signal('', ...(ngDevMode ? [{
19
+ debugName: "fragment"
20
+ }] : []));
21
+ queryParams = signal({}, ...(ngDevMode ? [{
22
+ debugName: "queryParams"
23
+ }] : []));
24
+ path = signal('', ...(ngDevMode ? [{
25
+ debugName: "path"
26
+ }] : []));
27
+ serializer = inject(UrlSerializer);
28
+ constructor() {
29
+ this.updateState();
30
+ this.router.events?.subscribe(e => {
31
+ if (e instanceof NavigationEnd) {
32
+ this.updateState();
33
+ }
34
+ });
35
+ }
36
+ updateState() {
37
+ const {
38
+ fragment,
39
+ root,
40
+ queryParams
41
+ } = this.stateManager.getCurrentUrlTree();
42
+ this.fragment.set(fragment);
43
+ this.queryParams.set(queryParams);
44
+ this.path.set(this.serializer.serialize(new UrlTree(root)));
45
+ }
46
+ static ɵfac = i0.ɵɵngDeclareFactory({
47
+ minVersion: "12.0.0",
48
+ version: "21.2.0-next.0",
49
+ ngImport: i0,
50
+ type: ReactiveRouterState,
51
+ deps: [],
52
+ target: i0.ɵɵFactoryTarget.Injectable
53
+ });
54
+ static ɵprov = i0.ɵɵngDeclareInjectable({
55
+ minVersion: "12.0.0",
56
+ version: "21.2.0-next.0",
57
+ ngImport: i0,
58
+ type: ReactiveRouterState,
59
+ providedIn: 'root'
60
+ });
61
+ }
62
+ i0.ɵɵngDeclareClassMetadata({
63
+ minVersion: "12.0.0",
64
+ version: "21.2.0-next.0",
65
+ ngImport: i0,
66
+ type: ReactiveRouterState,
67
+ decorators: [{
68
+ type: Injectable,
69
+ args: [{
70
+ providedIn: 'root'
71
+ }]
72
+ }],
73
+ ctorParameters: () => []
74
+ });
15
75
  class RouterLink {
16
76
  router;
17
77
  route;
@@ -19,7 +79,15 @@ class RouterLink {
19
79
  renderer;
20
80
  el;
21
81
  locationStrategy;
22
- reactiveHref = signal(null, ...(ngDevMode ? [{
82
+ hrefAttributeValue = inject(new HostAttributeToken('href'), {
83
+ optional: true
84
+ });
85
+ reactiveHref = linkedSignal(() => {
86
+ if (!this.isAnchorElement) {
87
+ return this.hrefAttributeValue;
88
+ }
89
+ return this.computeHref(this._urlTree());
90
+ }, ...(ngDevMode ? [{
23
91
  debugName: "reactiveHref"
24
92
  }] : []));
25
93
  get href() {
@@ -28,20 +96,112 @@ class RouterLink {
28
96
  set href(value) {
29
97
  this.reactiveHref.set(value);
30
98
  }
31
- target;
32
- queryParams;
33
- fragment;
34
- queryParamsHandling;
35
- state;
36
- info;
37
- relativeTo;
99
+ set target(value) {
100
+ this._target.set(value);
101
+ }
102
+ get target() {
103
+ return untracked(this._target);
104
+ }
105
+ _target = signal(undefined, ...(ngDevMode ? [{
106
+ debugName: "_target"
107
+ }] : []));
108
+ set queryParams(value) {
109
+ this._queryParams.set(value);
110
+ }
111
+ get queryParams() {
112
+ return untracked(this._queryParams);
113
+ }
114
+ _queryParams = signal(undefined, {
115
+ ...(ngDevMode ? {
116
+ debugName: "_queryParams"
117
+ } : {}),
118
+ equal: () => false
119
+ });
120
+ set fragment(value) {
121
+ this._fragment.set(value);
122
+ }
123
+ get fragment() {
124
+ return untracked(this._fragment);
125
+ }
126
+ _fragment = signal(undefined, ...(ngDevMode ? [{
127
+ debugName: "_fragment"
128
+ }] : []));
129
+ set queryParamsHandling(value) {
130
+ this._queryParamsHandling.set(value);
131
+ }
132
+ get queryParamsHandling() {
133
+ return untracked(this._queryParamsHandling);
134
+ }
135
+ _queryParamsHandling = signal(undefined, ...(ngDevMode ? [{
136
+ debugName: "_queryParamsHandling"
137
+ }] : []));
138
+ set state(value) {
139
+ this._state.set(value);
140
+ }
141
+ get state() {
142
+ return untracked(this._state);
143
+ }
144
+ _state = signal(undefined, {
145
+ ...(ngDevMode ? {
146
+ debugName: "_state"
147
+ } : {}),
148
+ equal: () => false
149
+ });
150
+ set info(value) {
151
+ this._info.set(value);
152
+ }
153
+ get info() {
154
+ return untracked(this._info);
155
+ }
156
+ _info = signal(undefined, {
157
+ ...(ngDevMode ? {
158
+ debugName: "_info"
159
+ } : {}),
160
+ equal: () => false
161
+ });
162
+ set relativeTo(value) {
163
+ this._relativeTo.set(value);
164
+ }
165
+ get relativeTo() {
166
+ return untracked(this._relativeTo);
167
+ }
168
+ _relativeTo = signal(undefined, ...(ngDevMode ? [{
169
+ debugName: "_relativeTo"
170
+ }] : []));
171
+ set preserveFragment(value) {
172
+ this._preserveFragment.set(value);
173
+ }
174
+ get preserveFragment() {
175
+ return untracked(this._preserveFragment);
176
+ }
177
+ _preserveFragment = signal(false, ...(ngDevMode ? [{
178
+ debugName: "_preserveFragment"
179
+ }] : []));
180
+ set skipLocationChange(value) {
181
+ this._skipLocationChange.set(value);
182
+ }
183
+ get skipLocationChange() {
184
+ return untracked(this._skipLocationChange);
185
+ }
186
+ _skipLocationChange = signal(false, ...(ngDevMode ? [{
187
+ debugName: "_skipLocationChange"
188
+ }] : []));
189
+ set replaceUrl(value) {
190
+ this._replaceUrl.set(value);
191
+ }
192
+ get replaceUrl() {
193
+ return untracked(this._replaceUrl);
194
+ }
195
+ _replaceUrl = signal(false, ...(ngDevMode ? [{
196
+ debugName: "_replaceUrl"
197
+ }] : []));
38
198
  isAnchorElement;
39
- subscription;
40
199
  onChanges = new Subject();
41
200
  applicationErrorHandler = inject(_INTERNAL_APPLICATION_ERROR_HANDLER);
42
201
  options = inject(ROUTER_CONFIGURATION, {
43
202
  optional: true
44
203
  });
204
+ reactiveRouterState = inject(ReactiveRouterState);
45
205
  constructor(router, route, tabIndexAttribute, renderer, el, locationStrategy) {
46
206
  this.router = router;
47
207
  this.route = route;
@@ -49,29 +209,16 @@ class RouterLink {
49
209
  this.renderer = renderer;
50
210
  this.el = el;
51
211
  this.locationStrategy = locationStrategy;
52
- this.reactiveHref.set(inject(new HostAttributeToken('href'), {
53
- optional: true
54
- }));
55
212
  const tagName = el.nativeElement.tagName?.toLowerCase();
56
213
  this.isAnchorElement = tagName === 'a' || tagName === 'area' || !!(typeof customElements === 'object' && customElements.get(tagName)?.observedAttributes?.includes?.('href'));
57
- if (this.isAnchorElement) {
58
- this.setTabIndexIfNotOnNativeEl('0');
59
- this.subscribeToNavigationEventsIfNecessary();
60
- }
61
- }
62
- subscribeToNavigationEventsIfNecessary() {
63
- if (this.subscription !== undefined) {
64
- return;
214
+ if (typeof ngDevMode !== 'undefined' && ngDevMode) {
215
+ effect(() => {
216
+ if (isUrlTree(this.routerLinkInput()) && (this._fragment() !== undefined || this._queryParams() || this._queryParamsHandling() || this._preserveFragment() || this._relativeTo())) {
217
+ throw new _RuntimeError(4017, 'Cannot configure queryParams or fragment when using a UrlTree as the routerLink input value.');
218
+ }
219
+ });
65
220
  }
66
- this.subscription = this.router.events.subscribe(s => {
67
- if (s instanceof NavigationEnd) {
68
- this.updateHref();
69
- }
70
- });
71
221
  }
72
- preserveFragment = false;
73
- skipLocationChange = false;
74
- replaceUrl = false;
75
222
  setTabIndexIfNotOnNativeEl(newTabIndex) {
76
223
  if (this.tabIndexAttribute != null || this.isAnchorElement) {
77
224
  return;
@@ -79,30 +226,26 @@ class RouterLink {
79
226
  this.applyAttributeValue('tabindex', newTabIndex);
80
227
  }
81
228
  ngOnChanges(changes) {
82
- if (ngDevMode && isUrlTree(this.routerLinkInput) && (this.fragment !== undefined || this.queryParams || this.queryParamsHandling || this.preserveFragment || this.relativeTo)) {
83
- throw new _RuntimeError(4017, 'Cannot configure queryParams or fragment when using a UrlTree as the routerLink input value.');
84
- }
85
- if (this.isAnchorElement) {
86
- this.updateHref();
87
- }
88
229
  this.onChanges.next(this);
89
230
  }
90
- routerLinkInput = null;
231
+ routerLinkInput = signal(null, ...(ngDevMode ? [{
232
+ debugName: "routerLinkInput"
233
+ }] : []));
91
234
  set routerLink(commandsOrUrlTree) {
92
235
  if (commandsOrUrlTree == null) {
93
- this.routerLinkInput = null;
236
+ this.routerLinkInput.set(null);
94
237
  this.setTabIndexIfNotOnNativeEl(null);
95
238
  } else {
96
239
  if (isUrlTree(commandsOrUrlTree)) {
97
- this.routerLinkInput = commandsOrUrlTree;
240
+ this.routerLinkInput.set(commandsOrUrlTree);
98
241
  } else {
99
- this.routerLinkInput = Array.isArray(commandsOrUrlTree) ? commandsOrUrlTree : [commandsOrUrlTree];
242
+ this.routerLinkInput.set(Array.isArray(commandsOrUrlTree) ? commandsOrUrlTree : [commandsOrUrlTree]);
100
243
  }
101
244
  this.setTabIndexIfNotOnNativeEl('0');
102
245
  }
103
246
  }
104
247
  onClick(button, ctrlKey, shiftKey, altKey, metaKey) {
105
- const urlTree = this.urlTree;
248
+ const urlTree = this._urlTree();
106
249
  if (urlTree === null) {
107
250
  return true;
108
251
  }
@@ -125,13 +268,7 @@ class RouterLink {
125
268
  });
126
269
  return !this.isAnchorElement;
127
270
  }
128
- ngOnDestroy() {
129
- this.subscription?.unsubscribe();
130
- }
131
- updateHref() {
132
- const urlTree = this.urlTree;
133
- this.reactiveHref.set(urlTree !== null && this.locationStrategy ? this.locationStrategy?.prepareExternalUrl(this.router.serializeUrl(urlTree)) ?? '' : null);
134
- }
271
+ ngOnDestroy() {}
135
272
  applyAttributeValue(attrName, attrValue) {
136
273
  const renderer = this.renderer;
137
274
  const nativeElement = this.el.nativeElement;
@@ -141,23 +278,43 @@ class RouterLink {
141
278
  renderer.removeAttribute(nativeElement, attrName);
142
279
  }
143
280
  }
144
- get urlTree() {
145
- if (this.routerLinkInput === null) {
281
+ _urlTree = computed(() => {
282
+ this.reactiveRouterState.path();
283
+ if (this._preserveFragment()) {
284
+ this.reactiveRouterState.fragment();
285
+ }
286
+ const shouldTrackParams = handling => handling === 'preserve' || handling === 'merge';
287
+ if (shouldTrackParams(this._queryParamsHandling()) || shouldTrackParams(this.options?.defaultQueryParamsHandling)) {
288
+ this.reactiveRouterState.queryParams();
289
+ }
290
+ const routerLinkInput = this.routerLinkInput();
291
+ if (routerLinkInput === null || !this.router.createUrlTree) {
146
292
  return null;
147
- } else if (isUrlTree(this.routerLinkInput)) {
148
- return this.routerLinkInput;
293
+ } else if (isUrlTree(routerLinkInput)) {
294
+ return routerLinkInput;
149
295
  }
150
- return this.router.createUrlTree(this.routerLinkInput, {
151
- relativeTo: this.relativeTo !== undefined ? this.relativeTo : this.route,
152
- queryParams: this.queryParams,
153
- fragment: this.fragment,
154
- queryParamsHandling: this.queryParamsHandling,
155
- preserveFragment: this.preserveFragment
296
+ return this.router.createUrlTree(routerLinkInput, {
297
+ relativeTo: this._relativeTo() !== undefined ? this._relativeTo() : this.route,
298
+ queryParams: this._queryParams(),
299
+ fragment: this._fragment(),
300
+ queryParamsHandling: this._queryParamsHandling(),
301
+ preserveFragment: this._preserveFragment()
156
302
  });
303
+ }, {
304
+ ...(ngDevMode ? {
305
+ debugName: "_urlTree"
306
+ } : {}),
307
+ equal: (a, b) => this.computeHref(a) === this.computeHref(b)
308
+ });
309
+ get urlTree() {
310
+ return untracked(this._urlTree);
311
+ }
312
+ computeHref(urlTree) {
313
+ return urlTree !== null && this.locationStrategy ? this.locationStrategy?.prepareExternalUrl(this.router.serializeUrl(urlTree)) ?? '' : null;
157
314
  }
158
315
  static ɵfac = i0.ɵɵngDeclareFactory({
159
316
  minVersion: "12.0.0",
160
- version: "21.1.2",
317
+ version: "21.2.0-next.0",
161
318
  ngImport: i0,
162
319
  type: RouterLink,
163
320
  deps: [{
@@ -178,7 +335,7 @@ class RouterLink {
178
335
  });
179
336
  static ɵdir = i0.ɵɵngDeclareDirective({
180
337
  minVersion: "16.1.0",
181
- version: "21.1.2",
338
+ version: "21.2.0-next.0",
182
339
  type: RouterLink,
183
340
  isStandalone: true,
184
341
  selector: "[routerLink]",
@@ -201,7 +358,7 @@ class RouterLink {
201
358
  },
202
359
  properties: {
203
360
  "attr.href": "reactiveHref()",
204
- "attr.target": "this.target"
361
+ "attr.target": "_target()"
205
362
  }
206
363
  },
207
364
  usesOnChanges: true,
@@ -210,7 +367,7 @@ class RouterLink {
210
367
  }
211
368
  i0.ɵɵngDeclareClassMetadata({
212
369
  minVersion: "12.0.0",
213
- version: "21.1.2",
370
+ version: "21.2.0-next.0",
214
371
  ngImport: i0,
215
372
  type: RouterLink,
216
373
  decorators: [{
@@ -218,7 +375,8 @@ i0.ɵɵngDeclareClassMetadata({
218
375
  args: [{
219
376
  selector: '[routerLink]',
220
377
  host: {
221
- '[attr.href]': 'reactiveHref()'
378
+ '[attr.href]': 'reactiveHref()',
379
+ '[attr.target]': '_target()'
222
380
  }
223
381
  }]
224
382
  }],
@@ -241,9 +399,6 @@ i0.ɵɵngDeclareClassMetadata({
241
399
  }],
242
400
  propDecorators: {
243
401
  target: [{
244
- type: HostBinding,
245
- args: ['attr.target']
246
- }, {
247
402
  type: Input
248
403
  }],
249
404
  queryParams: [{
@@ -390,7 +545,7 @@ class RouterLinkActive {
390
545
  }
391
546
  static ɵfac = i0.ɵɵngDeclareFactory({
392
547
  minVersion: "12.0.0",
393
- version: "21.1.2",
548
+ version: "21.2.0-next.0",
394
549
  ngImport: i0,
395
550
  type: RouterLinkActive,
396
551
  deps: [{
@@ -406,7 +561,7 @@ class RouterLinkActive {
406
561
  });
407
562
  static ɵdir = i0.ɵɵngDeclareDirective({
408
563
  minVersion: "14.0.0",
409
- version: "21.1.2",
564
+ version: "21.2.0-next.0",
410
565
  type: RouterLinkActive,
411
566
  isStandalone: true,
412
567
  selector: "[routerLinkActive]",
@@ -430,7 +585,7 @@ class RouterLinkActive {
430
585
  }
431
586
  i0.ɵɵngDeclareClassMetadata({
432
587
  minVersion: "12.0.0",
433
- version: "21.1.2",
588
+ version: "21.2.0-next.0",
434
589
  ngImport: i0,
435
590
  type: RouterLinkActive,
436
591
  decorators: [{
@@ -481,7 +636,7 @@ class PreloadAllModules {
481
636
  }
482
637
  static ɵfac = i0.ɵɵngDeclareFactory({
483
638
  minVersion: "12.0.0",
484
- version: "21.1.2",
639
+ version: "21.2.0-next.0",
485
640
  ngImport: i0,
486
641
  type: PreloadAllModules,
487
642
  deps: [],
@@ -489,7 +644,7 @@ class PreloadAllModules {
489
644
  });
490
645
  static ɵprov = i0.ɵɵngDeclareInjectable({
491
646
  minVersion: "12.0.0",
492
- version: "21.1.2",
647
+ version: "21.2.0-next.0",
493
648
  ngImport: i0,
494
649
  type: PreloadAllModules,
495
650
  providedIn: 'root'
@@ -497,7 +652,7 @@ class PreloadAllModules {
497
652
  }
498
653
  i0.ɵɵngDeclareClassMetadata({
499
654
  minVersion: "12.0.0",
500
- version: "21.1.2",
655
+ version: "21.2.0-next.0",
501
656
  ngImport: i0,
502
657
  type: PreloadAllModules,
503
658
  decorators: [{
@@ -513,7 +668,7 @@ class NoPreloading {
513
668
  }
514
669
  static ɵfac = i0.ɵɵngDeclareFactory({
515
670
  minVersion: "12.0.0",
516
- version: "21.1.2",
671
+ version: "21.2.0-next.0",
517
672
  ngImport: i0,
518
673
  type: NoPreloading,
519
674
  deps: [],
@@ -521,7 +676,7 @@ class NoPreloading {
521
676
  });
522
677
  static ɵprov = i0.ɵɵngDeclareInjectable({
523
678
  minVersion: "12.0.0",
524
- version: "21.1.2",
679
+ version: "21.2.0-next.0",
525
680
  ngImport: i0,
526
681
  type: NoPreloading,
527
682
  providedIn: 'root'
@@ -529,7 +684,7 @@ class NoPreloading {
529
684
  }
530
685
  i0.ɵɵngDeclareClassMetadata({
531
686
  minVersion: "12.0.0",
532
- version: "21.1.2",
687
+ version: "21.2.0-next.0",
533
688
  ngImport: i0,
534
689
  type: NoPreloading,
535
690
  decorators: [{
@@ -610,7 +765,7 @@ class RouterPreloader {
610
765
  }
611
766
  static ɵfac = i0.ɵɵngDeclareFactory({
612
767
  minVersion: "12.0.0",
613
- version: "21.1.2",
768
+ version: "21.2.0-next.0",
614
769
  ngImport: i0,
615
770
  type: RouterPreloader,
616
771
  deps: [{
@@ -626,7 +781,7 @@ class RouterPreloader {
626
781
  });
627
782
  static ɵprov = i0.ɵɵngDeclareInjectable({
628
783
  minVersion: "12.0.0",
629
- version: "21.1.2",
784
+ version: "21.2.0-next.0",
630
785
  ngImport: i0,
631
786
  type: RouterPreloader,
632
787
  providedIn: 'root'
@@ -634,7 +789,7 @@ class RouterPreloader {
634
789
  }
635
790
  i0.ɵɵngDeclareClassMetadata({
636
791
  minVersion: "12.0.0",
637
- version: "21.1.2",
792
+ version: "21.2.0-next.0",
638
793
  ngImport: i0,
639
794
  type: RouterPreloader,
640
795
  decorators: [{
@@ -736,7 +891,7 @@ class RouterScroller {
736
891
  }
737
892
  static ɵfac = i0.ɵɵngDeclareFactory({
738
893
  minVersion: "12.0.0",
739
- version: "21.1.2",
894
+ version: "21.2.0-next.0",
740
895
  ngImport: i0,
741
896
  type: RouterScroller,
742
897
  deps: "invalid",
@@ -744,14 +899,14 @@ class RouterScroller {
744
899
  });
745
900
  static ɵprov = i0.ɵɵngDeclareInjectable({
746
901
  minVersion: "12.0.0",
747
- version: "21.1.2",
902
+ version: "21.2.0-next.0",
748
903
  ngImport: i0,
749
904
  type: RouterScroller
750
905
  });
751
906
  }
752
907
  i0.ɵɵngDeclareClassMetadata({
753
908
  minVersion: "12.0.0",
754
- version: "21.1.2",
909
+ version: "21.2.0-next.0",
755
910
  ngImport: i0,
756
911
  type: RouterScroller,
757
912
  decorators: [{
@@ -807,7 +962,9 @@ class NavigationStateManager extends StateManager {
807
962
  path,
808
963
  state
809
964
  }) => {
810
- listener(path, state, 'popstate');
965
+ listener(path, state, 'popstate', !this.precommitHandlerSupported ? {
966
+ replaceUrl: true
967
+ } : {});
811
968
  });
812
969
  return this.nonRouterEntryChangeListener;
813
970
  }
@@ -818,19 +975,42 @@ class NavigationStateManager extends StateManager {
818
975
  };
819
976
  if (e instanceof NavigationStart) {
820
977
  this.updateStateMemento();
978
+ if (this.precommitHandlerSupported) {
979
+ this.maybeCreateNavigationForTransition(transition);
980
+ }
821
981
  } else if (e instanceof NavigationSkipped) {
822
982
  this.finishNavigation();
823
983
  this.commitTransition(transition);
824
- } else if (e instanceof RoutesRecognized) {
825
- if (this.urlUpdateStrategy === 'eager' && !transition.extras.skipLocationChange) {
826
- this.createNavigationForTransition(transition);
827
- }
984
+ } else if (e instanceof BeforeRoutesRecognized) {
985
+ transition.routesRecognizeHandler.deferredHandle = new Promise(async resolve => {
986
+ if (this.urlUpdateStrategy === 'eager') {
987
+ try {
988
+ this.maybeCreateNavigationForTransition(transition);
989
+ await this.currentNavigation.commitUrl?.();
990
+ } catch {
991
+ return;
992
+ }
993
+ }
994
+ resolve();
995
+ });
828
996
  } else if (e instanceof BeforeActivateRoutes) {
829
- this.commitTransition(transition);
830
- if (this.urlUpdateStrategy === 'deferred' && !transition.extras.skipLocationChange) {
831
- this.createNavigationForTransition(transition);
832
- }
997
+ transition.beforeActivateHandler.deferredHandle = new Promise(async resolve => {
998
+ if (this.urlUpdateStrategy === 'deferred') {
999
+ try {
1000
+ this.maybeCreateNavigationForTransition(transition);
1001
+ await this.currentNavigation.commitUrl?.();
1002
+ } catch {
1003
+ return;
1004
+ }
1005
+ }
1006
+ this.commitTransition(transition);
1007
+ resolve();
1008
+ });
833
1009
  } else if (e instanceof NavigationCancel || e instanceof NavigationError) {
1010
+ const redirectingBeforeUrlCommit = e instanceof NavigationCancel && e.code === NavigationCancellationCode.Redirect && !!this.currentNavigation.commitUrl;
1011
+ if (redirectingBeforeUrlCommit) {
1012
+ return;
1013
+ }
834
1014
  void this.cancel(transition, e);
835
1015
  } else if (e instanceof NavigationEnd) {
836
1016
  const {
@@ -847,11 +1027,12 @@ class NavigationStateManager extends StateManager {
847
1027
  });
848
1028
  }
849
1029
  }
850
- createNavigationForTransition(transition) {
1030
+ maybeCreateNavigationForTransition(transition) {
851
1031
  const {
852
- navigationEvent
1032
+ navigationEvent,
1033
+ commitUrl
853
1034
  } = this.currentNavigation;
854
- if (navigationEvent && navigationEvent.navigationType === 'traverse' && this.eventAndRouterDestinationsMatch(navigationEvent, transition)) {
1035
+ if (commitUrl || navigationEvent && (navigationEvent.navigationType === 'traverse' || navigationEvent.navigationType === 'reload') && this.eventAndRouterDestinationsMatch(navigationEvent, transition)) {
855
1036
  return;
856
1037
  }
857
1038
  this.currentNavigation.removeAbortListener?.();
@@ -880,6 +1061,7 @@ class NavigationStateManager extends StateManager {
880
1061
  }));
881
1062
  }
882
1063
  finishNavigation() {
1064
+ this.currentNavigation.commitUrl?.();
883
1065
  this.currentNavigation?.resolveHandler?.();
884
1066
  this.currentNavigation = {};
885
1067
  }
@@ -929,7 +1111,7 @@ class NavigationStateManager extends StateManager {
929
1111
  this.rawUrlTree = traversalReset ? this.stateMemento.rawUrlTree : this.urlHandlingStrategy.merge(this.currentUrlTree, finalUrl ?? this.rawUrlTree);
930
1112
  }
931
1113
  handleNavigate(event) {
932
- if (!event.canIntercept || event.navigationType === 'reload') {
1114
+ if (!event.canIntercept) {
933
1115
  return;
934
1116
  }
935
1117
  const routerInfo = event?.info?.ɵrouterInfo;
@@ -962,16 +1144,50 @@ class NavigationStateManager extends StateManager {
962
1144
  resolve: resolveHandler,
963
1145
  reject: rejectHandler
964
1146
  } = _promiseWithResolvers();
1147
+ const {
1148
+ promise: precommitHandlerPromise,
1149
+ resolve: resolvePrecommitHandler,
1150
+ reject: rejectPrecommitHandler
1151
+ } = _promiseWithResolvers();
1152
+ this.currentNavigation.rejectNavigateEvent = () => {
1153
+ event.signal.removeEventListener('abort', abortHandler);
1154
+ rejectPrecommitHandler();
1155
+ rejectHandler();
1156
+ };
965
1157
  this.currentNavigation.resolveHandler = () => {
966
1158
  this.currentNavigation.removeAbortListener?.();
967
1159
  resolveHandler();
968
1160
  };
969
- this.currentNavigation.rejectNavigateEvent = () => {
970
- this.currentNavigation.removeAbortListener?.();
971
- rejectHandler();
972
- };
973
1161
  handlerPromise.catch(() => {});
1162
+ precommitHandlerPromise.catch(() => {});
974
1163
  interceptOptions.handler = () => handlerPromise;
1164
+ if (this.deferredCommitSupported(event)) {
1165
+ const redirect = new Promise(resolve => {
1166
+ interceptOptions.precommitHandler = controller => {
1167
+ resolve(controller.redirect.bind(controller));
1168
+ return precommitHandlerPromise;
1169
+ };
1170
+ });
1171
+ this.currentNavigation.commitUrl = async () => {
1172
+ this.currentNavigation.commitUrl = undefined;
1173
+ const transition = this.currentNavigation.routerTransition;
1174
+ if (transition && !transition.extras.skipLocationChange) {
1175
+ const internalPath = this.createBrowserPath(transition);
1176
+ const history = this.location.isCurrentPathEqualTo(internalPath) || !!transition.extras.replaceUrl ? 'replace' : 'push';
1177
+ const state = {
1178
+ ...transition.extras.state,
1179
+ navigationId: transition.id
1180
+ };
1181
+ const pathOrUrl = this.location.prepareExternalUrl(internalPath);
1182
+ (await redirect)(pathOrUrl, {
1183
+ state,
1184
+ history
1185
+ });
1186
+ }
1187
+ resolvePrecommitHandler();
1188
+ return await this.navigation.transition?.committed;
1189
+ };
1190
+ }
975
1191
  event.intercept(interceptOptions);
976
1192
  if (!isTriggeredByRouterTransition) {
977
1193
  this.handleNavigateEventTriggeredOutsideRouterAPIs(event);
@@ -991,9 +1207,12 @@ class NavigationStateManager extends StateManager {
991
1207
  const routerDestination = this.location.prepareExternalUrl(internalPath);
992
1208
  return new URL(routerDestination, eventDestination.origin).href === eventDestination.href;
993
1209
  }
1210
+ deferredCommitSupported(event) {
1211
+ return this.precommitHandlerSupported && event.cancelable && event.navigationType !== 'traverse';
1212
+ }
994
1213
  static ɵfac = i0.ɵɵngDeclareFactory({
995
1214
  minVersion: "12.0.0",
996
- version: "21.1.2",
1215
+ version: "21.2.0-next.0",
997
1216
  ngImport: i0,
998
1217
  type: NavigationStateManager,
999
1218
  deps: [],
@@ -1001,7 +1220,7 @@ class NavigationStateManager extends StateManager {
1001
1220
  });
1002
1221
  static ɵprov = i0.ɵɵngDeclareInjectable({
1003
1222
  minVersion: "12.0.0",
1004
- version: "21.1.2",
1223
+ version: "21.2.0-next.0",
1005
1224
  ngImport: i0,
1006
1225
  type: NavigationStateManager,
1007
1226
  providedIn: 'root'
@@ -1009,7 +1228,7 @@ class NavigationStateManager extends StateManager {
1009
1228
  }
1010
1229
  i0.ɵɵngDeclareClassMetadata({
1011
1230
  minVersion: "12.0.0",
1012
- version: "21.1.2",
1231
+ version: "21.2.0-next.0",
1013
1232
  ngImport: i0,
1014
1233
  type: NavigationStateManager,
1015
1234
  decorators: [{
@@ -1308,7 +1527,7 @@ class RouterModule {
1308
1527
  }
1309
1528
  static ɵfac = i0.ɵɵngDeclareFactory({
1310
1529
  minVersion: "12.0.0",
1311
- version: "21.1.2",
1530
+ version: "21.2.0-next.0",
1312
1531
  ngImport: i0,
1313
1532
  type: RouterModule,
1314
1533
  deps: [],
@@ -1316,7 +1535,7 @@ class RouterModule {
1316
1535
  });
1317
1536
  static ɵmod = i0.ɵɵngDeclareNgModule({
1318
1537
  minVersion: "14.0.0",
1319
- version: "21.1.2",
1538
+ version: "21.2.0-next.0",
1320
1539
  ngImport: i0,
1321
1540
  type: RouterModule,
1322
1541
  imports: [RouterOutlet, RouterLink, RouterLinkActive, _EmptyOutletComponent],
@@ -1324,14 +1543,14 @@ class RouterModule {
1324
1543
  });
1325
1544
  static ɵinj = i0.ɵɵngDeclareInjector({
1326
1545
  minVersion: "12.0.0",
1327
- version: "21.1.2",
1546
+ version: "21.2.0-next.0",
1328
1547
  ngImport: i0,
1329
1548
  type: RouterModule
1330
1549
  });
1331
1550
  }
1332
1551
  i0.ɵɵngDeclareClassMetadata({
1333
1552
  minVersion: "12.0.0",
1334
- version: "21.1.2",
1553
+ version: "21.2.0-next.0",
1335
1554
  ngImport: i0,
1336
1555
  type: RouterModule,
1337
1556
  decorators: [{