Skip to content

Commit 8c2461d

Browse files
fix(lazyLoad): Use UrlService.match() to retry url sync after successful lazy load triggered by url
Closes #19
1 parent 32e64f0 commit 8c2461d

File tree

2 files changed

+45
-25
lines changed

2 files changed

+45
-25
lines changed

src/hooks/lazyLoad.ts

+22-25
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {TransitionHookFn} from "../transition/interface";
55
import {StateDeclaration, LazyLoadResult} from "../state/interface";
66
import {State} from "../state/stateObject";
77
import {services} from "../common/coreservices";
8+
import { StateRule } from "../url/interface";
89

910
/**
1011
* A [[TransitionHookFn]] that performs lazy loading
@@ -33,36 +34,32 @@ import {services} from "../common/coreservices";
3334
const lazyLoadHook: TransitionHookFn = (transition: Transition) => {
3435
const transitionSource = (trans: Transition) =>
3536
trans.redirectedFrom() ? transitionSource(trans.redirectedFrom()) : trans.options().source;
37+
let router = transition.router;
3638

3739
function retryOriginalTransition() {
38-
if (transitionSource(transition) === 'url') {
39-
let $loc = transition.router.urlService,
40-
$reg = transition.router.stateRegistry,
41-
path = $loc.path(),
42-
search = $loc.search(),
43-
hash = $loc.hash();
44-
45-
let matchState = state =>
46-
[state, state.url && state.url.exec(path, search, hash)];
47-
48-
let matches = $reg.get()
49-
.map(s => s.$$state())
50-
.map(matchState)
51-
.filter(([state, params]) => !!params);
52-
53-
if (matches.length) {
54-
let [state, params] = matches[0];
55-
return transition.router.stateService.target(state, params, transition.options());
56-
}
40+
if (transitionSource(transition) !== 'url') {
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 router.stateService.target(orig.identifier(), orig.params(), orig.options());
45+
}
5746

58-
transition.router.urlRouter.sync();
59-
return;
47+
// The original transition was triggered via url sync
48+
// Run the URL rules and find the best match
49+
let $url = router.urlService;
50+
let result = $url.match($url.parts());
51+
let rule = result && result.rule;
52+
53+
// If the best match is a state, redirect the transition (instead
54+
// of calling sync() which supersedes the current transition)
55+
if (rule && rule.type === "STATE") {
56+
let state = (rule as StateRule).state;
57+
let params = result.match;
58+
return router.stateService.target(state, params, transition.options());
6059
}
6160

62-
// The original transition was not triggered via url sync
63-
// The lazy state should be loaded now, so re-try the original transition
64-
let orig = transition.targetState();
65-
return transition.router.stateService.target(orig.identifier(), orig.params(), orig.options());
61+
// No matching state found, so let .sync() choose the best non-state match/otherwise
62+
router.urlRouter.sync();
6663
}
6764

6865
let promises = transition.entering()

test/urlRouterSpec.ts

+23
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,29 @@ describe("UrlRouter", function () {
300300
expect(match.rule).toBe(CCC);
301301
});
302302
});
303+
304+
describe('lazy loaded state url', () => {
305+
it("should obey rule priority ordering", (done) => {
306+
let registry = router.stateRegistry;
307+
let loadedState;
308+
const lazyLoad = () => {
309+
loadedState = registry.register({ name: 'lazy', url: '/lazy' });
310+
return null;
311+
};
312+
313+
registry.register({ name: 'lazy.**', url: '/lazy', lazyLoad: lazyLoad });
314+
registry.register({ name: 'param', url: '/:param', });
315+
316+
router.transitionService.onSuccess({}, trans => {
317+
expect(trans.$to()).toBe(loadedState);
318+
expect(trans.redirectedFrom().to().name).toBe('lazy.**');
319+
320+
done();
321+
});
322+
323+
router.urlService.url('/lazy');
324+
})
325+
})
303326
});
304327

305328
describe('UrlRouter.deferIntercept', () => {

0 commit comments

Comments
 (0)