@@ -12,7 +12,7 @@ import {BehaviorSubject, Observable, of, SubscriptionLike} from 'rxjs';
12
12
13
13
import { CreateUrlTreeStrategy } from './create_url_tree_strategy' ;
14
14
import { RuntimeErrorCode } from './errors' ;
15
- import { Event , NavigationTrigger } from './events' ;
15
+ import { Event , IMPERATIVE_NAVIGATION , NavigationTrigger } from './events' ;
16
16
import { NavigationBehaviorOptions , OnSameUrlNavigation , Routes } from './models' ;
17
17
import { Navigation , NavigationExtras , NavigationTransition , NavigationTransitions , RestoredState , UrlCreationOptions } from './navigation_transition' ;
18
18
import { TitleStrategy } from './page_title_strategy' ;
@@ -353,7 +353,8 @@ export class Router {
353
353
initialNavigation ( ) : void {
354
354
this . setUpLocationChangeListener ( ) ;
355
355
if ( ! this . navigationTransitions . hasRequestedNavigation ) {
356
- this . navigateByUrl ( this . location . path ( true ) , { replaceUrl : true } ) ;
356
+ const state = this . location . getState ( ) as RestoredState ;
357
+ this . navigateToSyncWithBrowser ( this . location . path ( true ) , IMPERATIVE_NAVIGATION , state ) ;
357
358
}
358
359
}
359
360
@@ -373,37 +374,49 @@ export class Router {
373
374
// The `setTimeout` was added in #12160 and is likely to support Angular/AngularJS
374
375
// hybrid apps.
375
376
setTimeout ( ( ) => {
376
- const extras : NavigationExtras = { replaceUrl : true } ;
377
-
378
- // TODO: restoredState should always include the entire state, regardless
379
- // of navigationId. This requires a breaking change to update the type on
380
- // NavigationStart’s restoredState, which currently requires navigationId
381
- // to always be present. The Router used to only restore history state if
382
- // a navigationId was present.
383
-
384
- // The stored navigationId is used by the RouterScroller to retrieve the scroll
385
- // position for the page.
386
- const restoredState = event . state ?. navigationId ? event . state : null ;
387
-
388
- // Separate to NavigationStart.restoredState, we must also restore the state to
389
- // history.state and generate a new navigationId, since it will be overwritten
390
- if ( event . state ) {
391
- const stateCopy = { ...event . state } as Partial < RestoredState > ;
392
- delete stateCopy . navigationId ;
393
- delete stateCopy . ɵrouterPageId ;
394
- if ( Object . keys ( stateCopy ) . length !== 0 ) {
395
- extras . state = stateCopy ;
396
- }
397
- }
398
-
399
- const urlTree = this . parseUrl ( event [ 'url' ] ! ) ;
400
- this . scheduleNavigation ( urlTree , source , restoredState , extras ) ;
377
+ this . navigateToSyncWithBrowser ( event [ 'url' ] ! , source , event . state ) ;
401
378
} , 0 ) ;
402
379
}
403
380
} ) ;
404
381
}
405
382
}
406
383
384
+ /**
385
+ * Schedules a router navigation to synchronize Router state with the browser state.
386
+ *
387
+ * This is done as a response to a popstate event and the initial navigation. These
388
+ * two scenarios represent times when the browser URL/state has been updated and
389
+ * the Router needs to respond to ensure its internal state matches.
390
+ */
391
+ private navigateToSyncWithBrowser (
392
+ url : string , source : NavigationTrigger , state : RestoredState | undefined ) {
393
+ const extras : NavigationExtras = { replaceUrl : true } ;
394
+
395
+ // TODO: restoredState should always include the entire state, regardless
396
+ // of navigationId. This requires a breaking change to update the type on
397
+ // NavigationStart’s restoredState, which currently requires navigationId
398
+ // to always be present. The Router used to only restore history state if
399
+ // a navigationId was present.
400
+
401
+ // The stored navigationId is used by the RouterScroller to retrieve the scroll
402
+ // position for the page.
403
+ const restoredState = state ?. navigationId ? state : null ;
404
+
405
+ // Separate to NavigationStart.restoredState, we must also restore the state to
406
+ // history.state and generate a new navigationId, since it will be overwritten
407
+ if ( state ) {
408
+ const stateCopy = { ...state } as Partial < RestoredState > ;
409
+ delete stateCopy . navigationId ;
410
+ delete stateCopy . ɵrouterPageId ;
411
+ if ( Object . keys ( stateCopy ) . length !== 0 ) {
412
+ extras . state = stateCopy ;
413
+ }
414
+ }
415
+
416
+ const urlTree = this . parseUrl ( url ) ;
417
+ this . scheduleNavigation ( urlTree , source , restoredState , extras ) ;
418
+ }
419
+
407
420
/** The current URL. */
408
421
get url ( ) : string {
409
422
return this . serializeUrl ( this . currentUrlTree ) ;
@@ -561,7 +574,7 @@ export class Router {
561
574
const urlTree = isUrlTree ( url ) ? url : this . parseUrl ( url ) ;
562
575
const mergedTree = this . urlHandlingStrategy . merge ( urlTree , this . rawUrlTree ) ;
563
576
564
- return this . scheduleNavigation ( mergedTree , 'imperative' , null , extras ) ;
577
+ return this . scheduleNavigation ( mergedTree , IMPERATIVE_NAVIGATION , null , extras ) ;
565
578
}
566
579
567
580
/**
@@ -686,10 +699,6 @@ export class Router {
686
699
687
700
let targetPageId : number ;
688
701
if ( this . canceledNavigationResolution === 'computed' ) {
689
- const isInitialPage = this . currentPageId === 0 ;
690
- if ( isInitialPage ) {
691
- restoredState = this . location . getState ( ) as RestoredState | null ;
692
- }
693
702
// If the `ɵrouterPageId` exist in the state then `targetpageId` should have the value of
694
703
// `ɵrouterPageId`. This is the case for something like a page refresh where we assign the
695
704
// target id to the previously set value for that page.
0 commit comments