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