Skip to content

Commit fe71ffb

Browse files
dummdidummbrandonroberts
authored andcommitted
feat(router-store): config option to dispatch ROUTER_NAVIGATION later
Part of #1263
1 parent 5c814a9 commit fe71ffb

File tree

2 files changed

+54
-1
lines changed

2 files changed

+54
-1
lines changed

modules/router-store/spec/integration.spec.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,44 @@ describe('integration spec', () => {
644644
done();
645645
});
646646
});
647+
648+
it('should dispatch ROUTER_NAVIGATION later when config options set to true', () => {
649+
const reducer = (state: string = '', action: RouterAction<any>) => {
650+
if (action.type === ROUTER_NAVIGATION) {
651+
return action.payload.routerState.url.toString();
652+
} else {
653+
return state;
654+
}
655+
};
656+
657+
createTestModule({
658+
reducers: { reducer },
659+
config: { dispatchNavActionOnEnd: true },
660+
});
661+
662+
const router: Router = TestBed.get(Router);
663+
const log = logOfRouterAndActionsAndStore();
664+
665+
router.navigateByUrl('/').then(() => {
666+
expect(log).toEqual([
667+
{ type: 'store', state: '' }, // init event. has nothing to do with the router
668+
{ type: 'store', state: '' }, // ROUTER_REQUEST event in the store
669+
{ type: 'action', action: ROUTER_REQUEST },
670+
{ type: 'router', event: 'NavigationStart', url: '/' },
671+
{ type: 'router', event: 'RoutesRecognized', url: '/' },
672+
/* new Router Lifecycle in Angular 4.3 */
673+
{ type: 'router', event: 'GuardsCheckStart', url: '/' },
674+
{ type: 'router', event: 'GuardsCheckEnd', url: '/' },
675+
{ type: 'router', event: 'ResolveStart', url: '/' },
676+
{ type: 'router', event: 'ResolveEnd', url: '/' },
677+
{ type: 'store', state: '/' }, // ROUTER_NAVIGATION event in the store
678+
{ type: 'action', action: ROUTER_NAVIGATION },
679+
{ type: 'store', state: '/' }, // ROUTER_NAVIGATED event in the store
680+
{ type: 'action', action: ROUTER_NAVIGATED },
681+
{ type: 'router', event: 'NavigationEnd', url: '/' },
682+
]);
683+
});
684+
});
647685
});
648686

649687
function createTestModule(

modules/router-store/src/router_store_module.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,13 @@ export function routerReducer<
176176
export interface StoreRouterConfig {
177177
stateKey?: string;
178178
serializer?: new () => RouterStateSerializer;
179+
/**
180+
* By default, ROUTER_NAVIGATION is dispatched before guards and resolvers run.
181+
* Therefore, the action could run too soon, for example
182+
* there may be a navigation cancel due to a guard saying the navigation is not allowed.
183+
* To run ROUTER_NAVIGATION after guards and resolvers, set this property to true.
184+
*/
185+
dispatchNavActionOnEnd?: boolean;
179186
}
180187

181188
export const _ROUTER_CONFIG = new InjectionToken(
@@ -200,6 +207,7 @@ export function _createRouterConfig(
200207
return {
201208
stateKey: DEFAULT_ROUTER_FEATURENAME,
202209
serializer: DefaultRouterStateSerializer,
210+
dispatchNavActionOnEnd: false,
203211
..._config,
204212
};
205213
}
@@ -342,15 +350,19 @@ export class StoreRouterConnectingModule {
342350
}
343351

344352
private setUpRouterEventsListener(): void {
353+
const dispatchNavLate = this.config.dispatchNavActionOnEnd;
354+
let routesRecognized: RoutesRecognized;
355+
345356
this.router.events.subscribe(event => {
346357
if (event instanceof NavigationStart) {
347358
if (this.trigger !== RouterTrigger.STORE) {
348359
this.dispatchRouterRequest(event);
349360
}
350361
} else if (event instanceof RoutesRecognized) {
362+
routesRecognized = event;
351363
this.routerState = this.serializer.serialize(event.state);
352364

353-
if (this.trigger !== RouterTrigger.STORE) {
365+
if (!dispatchNavLate && this.trigger !== RouterTrigger.STORE) {
354366
this.dispatchRouterNavigation(event);
355367
}
356368
} else if (event instanceof NavigationCancel) {
@@ -359,6 +371,9 @@ export class StoreRouterConnectingModule {
359371
this.dispatchRouterError(event);
360372
} else if (event instanceof NavigationEnd) {
361373
if (this.trigger !== RouterTrigger.STORE) {
374+
if (dispatchNavLate) {
375+
this.dispatchRouterNavigation(routesRecognized);
376+
}
362377
this.dispatchRouterNavigated(event);
363378
}
364379
this.trigger = RouterTrigger.NONE;

0 commit comments

Comments
 (0)