2
2
import { Transition } from "../transition/transition" ;
3
3
import { TransitionService } from "../transition/transitionService" ;
4
4
import { TransitionHookFn } from "../transition/interface" ;
5
- import { StateDeclaration } from "../state/interface" ;
5
+ import { StateDeclaration , LazyLoadResult } from "../state/interface" ;
6
6
import { State } from "../state/stateObject" ;
7
7
import { services } from "../common/coreservices" ;
8
8
@@ -22,42 +22,49 @@ import {services} from "../common/coreservices";
22
22
*/
23
23
const lazyLoadHook : TransitionHookFn = ( transition : Transition ) => {
24
24
var toState = transition . to ( ) ;
25
+ let registry = transition . router . stateRegistry ;
25
26
26
- function retryOriginalTransition ( newStates : State [ ] ) {
27
+ function retryOriginalTransition ( ) {
27
28
if ( transition . options ( ) . source === 'url' ) {
28
- let loc = services . location ;
29
- let path = loc . path ( ) , search = loc . search ( ) , hash = loc . hash ( ) ;
29
+ let loc = services . location , path = loc . path ( ) , search = loc . search ( ) , hash = loc . hash ( ) ;
30
+
31
+ let matchState = state => [ state , state . url && state . url . exec ( path , search , hash ) ] ;
32
+ let matches = registry . get ( ) . map ( s => s . $$state ( ) ) . map ( matchState ) . filter ( ( [ state , params ] ) => ! ! params ) ;
30
33
31
- let matchState = state => [ state , state . url . exec ( path , search , hash ) ] ;
32
- let matches = newStates . map ( matchState ) . filter ( ( [ state , params ] ) => ! ! params ) ;
33
34
if ( matches . length ) {
34
35
let [ state , params ] = matches [ 0 ] ;
35
36
return transition . router . stateService . target ( state , params , transition . options ( ) ) ;
36
37
}
37
38
transition . router . urlRouter . sync ( ) ;
38
39
}
39
40
40
- let state = transition . targetState ( ) . identifier ( ) ;
41
- let params = transition . params ( ) ;
42
- let options = transition . options ( ) ;
43
- return transition . router . stateService . target ( state , params , options ) ;
41
+ // The original transition was not triggered via url sync
42
+ // The lazy state should be loaded now, so re-try the original transition
43
+ let orig = transition . targetState ( ) ;
44
+ return transition . router . stateService . target ( orig . identifier ( ) , orig . params ( ) , orig . options ( ) ) ;
44
45
}
45
46
46
47
/**
47
48
* Replace the placeholder state with the newly loaded states from the NgModule.
48
49
*/
49
- function updateStateRegistry ( newStates : StateDeclaration [ ] ) {
50
- let registry = transition . router . stateRegistry ;
51
- let placeholderState = transition . to ( ) ;
50
+ function updateStateRegistry ( result : LazyLoadResult ) {
51
+ // deregister placeholder state
52
+ registry . deregister ( transition . $to ( ) ) ;
53
+ if ( result && Array . isArray ( result . states ) ) {
54
+ result . states . forEach ( state => registry . register ( state ) ) ;
55
+ }
56
+ }
52
57
53
- registry . deregister ( placeholderState ) ;
54
- newStates . forEach ( state => registry . register ( state ) ) ;
55
- return newStates . map ( state => registry . get ( state ) . $$state ( ) ) ;
58
+ let hook = toState . lazyLoad ;
59
+ // Store/get the lazy load promise on/from the hookfn so it doesn't get re-invoked
60
+ let promise = hook [ '_promise' ] ;
61
+ if ( ! promise ) {
62
+ promise = hook [ '_promise' ] = hook ( transition ) . then ( updateStateRegistry ) ;
63
+ const cleanup = ( ) => delete hook [ '_promise' ] ;
64
+ promise . catch ( cleanup , cleanup ) ;
56
65
}
57
-
58
- return toState . lazyLoad ( transition )
59
- . then ( updateStateRegistry )
60
- . then ( retryOriginalTransition )
66
+
67
+ return promise . then ( retryOriginalTransition ) ;
61
68
} ;
62
69
63
70
export const registerLazyLoadHook = ( transitionService : TransitionService ) =>
0 commit comments