Skip to content

Commit ab7de5c

Browse files
phillipzadabrandonroberts
authored andcommitted
feat(RouterStore): Add configurable option for router reducer name (#417)
Closes #410
1 parent 4db7d61 commit ab7de5c

File tree

4 files changed

+133
-10
lines changed

4 files changed

+133
-10
lines changed

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

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { StoreRouterConfig } from '../src/router_store_module';
12
import { Component, Provider } from '@angular/core';
23
import { TestBed } from '@angular/core/testing';
34
import { NavigationEnd, Router, RouterStateSnapshot } from '@angular/router';
@@ -457,7 +458,59 @@ describe('integration spec', () => {
457458
{ type: 'router', event: 'GuardsCheckEnd', url: '/next' },
458459
{ type: 'router', event: 'ResolveStart', url: '/next' },
459460
{ type: 'router', event: 'ResolveEnd', url: '/next' },
461+
{ type: 'router', event: 'NavigationEnd', url: '/next' },
462+
]);
460463

464+
done();
465+
});
466+
});
467+
468+
it('should work when defining state key', (done: any) => {
469+
const reducer = (state: string = '', action: RouterAction<any>) => {
470+
if (action.type === ROUTER_NAVIGATION) {
471+
return action.payload.routerState.url.toString();
472+
} else {
473+
return state;
474+
}
475+
};
476+
477+
createTestModule({
478+
reducers: { reducer },
479+
config: { stateKey: 'router-reducer' },
480+
});
481+
482+
const router: Router = TestBed.get(Router);
483+
const store = TestBed.get(Store);
484+
const log = logOfRouterAndStore(router, store);
485+
486+
router
487+
.navigateByUrl('/')
488+
.then(() => {
489+
expect(log).toEqual([
490+
{ type: 'store', state: '' }, // init event. has nothing to do with the router
491+
{ type: 'router', event: 'NavigationStart', url: '/' },
492+
{ type: 'router', event: 'RoutesRecognized', url: '/' },
493+
{ type: 'store', state: '/' }, // ROUTER_NAVIGATION event in the store
494+
{ type: 'router', event: 'GuardsCheckStart', url: '/' },
495+
{ type: 'router', event: 'GuardsCheckEnd', url: '/' },
496+
{ type: 'router', event: 'ResolveStart', url: '/' },
497+
{ type: 'router', event: 'ResolveEnd', url: '/' },
498+
{ type: 'router', event: 'NavigationEnd', url: '/' },
499+
]);
500+
})
501+
.then(() => {
502+
log.splice(0);
503+
return router.navigateByUrl('next');
504+
})
505+
.then(() => {
506+
expect(log).toEqual([
507+
{ type: 'router', event: 'NavigationStart', url: '/next' },
508+
{ type: 'router', event: 'RoutesRecognized', url: '/next' },
509+
{ type: 'store', state: '/next' },
510+
{ type: 'router', event: 'GuardsCheckStart', url: '/next' },
511+
{ type: 'router', event: 'GuardsCheckEnd', url: '/next' },
512+
{ type: 'router', event: 'ResolveStart', url: '/next' },
513+
{ type: 'router', event: 'ResolveEnd', url: '/next' },
461514
{ type: 'router', event: 'NavigationEnd', url: '/next' },
462515
]);
463516

@@ -472,6 +525,7 @@ function createTestModule(
472525
canActivate?: Function;
473526
canLoad?: Function;
474527
providers?: Provider[];
528+
config?: StoreRouterConfig;
475529
} = {}
476530
) {
477531
@Component({
@@ -503,7 +557,7 @@ function createTestModule(
503557
canLoad: ['CanLoadNext'],
504558
},
505559
]),
506-
StoreRouterConnectingModule,
560+
StoreRouterConnectingModule.forRoot(opts.config),
507561
],
508562
providers: [
509563
{

modules/router-store/src/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ export {
1212
RouterCancelPayload,
1313
RouterNavigationPayload,
1414
StoreRouterConnectingModule,
15+
StoreRouterConfig,
16+
StoreRouterConfigFunction,
17+
ROUTER_CONFIG,
18+
DEFAULT_ROUTER_FEATURENAME,
1519
} from './router_store_module';
1620

1721
export {

modules/router-store/src/router_store_module.ts

Lines changed: 73 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
import { NgModule } from '@angular/core';
1+
import {
2+
NgModule,
3+
ModuleWithProviders,
4+
InjectionToken,
5+
Inject,
6+
} from '@angular/core';
27
import {
38
NavigationCancel,
49
NavigationError,
@@ -107,6 +112,33 @@ export function routerReducer<T = RouterStateSnapshot>(
107112
}
108113
}
109114

115+
export type StoreRouterConfig = {
116+
stateKey?: string;
117+
};
118+
119+
export const _ROUTER_CONFIG = new InjectionToken(
120+
'@ngrx/router-store Internal Configuration'
121+
);
122+
export const ROUTER_CONFIG = new InjectionToken(
123+
'@ngrx/router-store Configuration'
124+
);
125+
export const DEFAULT_ROUTER_FEATURENAME = 'routerReducer';
126+
127+
export function _createDefaultRouterConfig(config: any): StoreRouterConfig {
128+
let _config = {};
129+
130+
if (typeof config === 'function') {
131+
_config = config();
132+
}
133+
134+
return {
135+
stateKey: DEFAULT_ROUTER_FEATURENAME,
136+
..._config,
137+
};
138+
}
139+
140+
export type StoreRouterConfigFunction = () => StoreRouterConfig;
141+
110142
/**
111143
* Connects RouterModule with StoreModule.
112144
*
@@ -152,21 +184,54 @@ export function routerReducer<T = RouterStateSnapshot>(
152184
@NgModule({
153185
providers: [
154186
{ provide: RouterStateSerializer, useClass: DefaultRouterStateSerializer },
187+
{
188+
provide: _ROUTER_CONFIG,
189+
useValue: { stateKey: DEFAULT_ROUTER_FEATURENAME },
190+
},
191+
{
192+
provide: ROUTER_CONFIG,
193+
useFactory: _createDefaultRouterConfig,
194+
deps: [_ROUTER_CONFIG],
195+
},
155196
],
156197
})
157198
export class StoreRouterConnectingModule {
199+
static forRoot(
200+
config?: StoreRouterConfig | StoreRouterConfigFunction
201+
): ModuleWithProviders;
202+
static forRoot(
203+
config: StoreRouterConfig | StoreRouterConfigFunction = {}
204+
): ModuleWithProviders {
205+
return {
206+
ngModule: StoreRouterConnectingModule,
207+
providers: [
208+
{ provide: _ROUTER_CONFIG, useValue: config },
209+
{
210+
provide: ROUTER_CONFIG,
211+
useFactory: _createDefaultRouterConfig,
212+
deps: [_ROUTER_CONFIG],
213+
},
214+
],
215+
};
216+
}
217+
158218
private routerState: RouterStateSnapshot;
159219
private storeState: any;
160220
private lastRoutesRecognized: RoutesRecognized;
161221

162222
private dispatchTriggeredByRouter: boolean = false; // used only in dev mode in combination with routerReducer
163223
private navigationTriggeredByDispatch: boolean = false; // used only in dev mode in combination with routerReducer
164224

225+
private stateKey: string;
226+
165227
constructor(
166228
private store: Store<any>,
167229
private router: Router,
168-
private serializer: RouterStateSerializer<RouterStateSnapshot>
230+
private serializer: RouterStateSerializer<RouterStateSnapshot>,
231+
@Inject(ROUTER_CONFIG) private config: StoreRouterConfig
169232
) {
233+
this.stateKey = this.config.stateKey as string;
234+
170235
this.setUpBeforePreactivationHook();
171236
this.setUpStoreStateListener();
172237
this.setUpStateRollbackEvents();
@@ -187,28 +252,28 @@ export class StoreRouterConnectingModule {
187252
this.store.subscribe(s => {
188253
this.storeState = s;
189254
});
190-
this.store.select('routerReducer').subscribe(() => {
255+
this.store.select(this.stateKey).subscribe(() => {
191256
this.navigateIfNeeded();
192257
});
193258
}
194259

195260
private shouldDispatchRouterNavigation(): boolean {
196-
if (!this.storeState['routerReducer']) return true;
261+
if (!this.storeState[this.stateKey]) return true;
197262
return !this.navigationTriggeredByDispatch;
198263
}
199264

200265
private navigateIfNeeded(): void {
201266
if (
202-
!this.storeState['routerReducer'] ||
203-
!this.storeState['routerReducer'].state
267+
!this.storeState[this.stateKey] ||
268+
!this.storeState[this.stateKey].state
204269
) {
205270
return;
206271
}
207272
if (this.dispatchTriggeredByRouter) return;
208273

209-
if (this.router.url !== this.storeState['routerReducer'].state.url) {
274+
if (this.router.url !== this.storeState[this.stateKey].state.url) {
210275
this.navigationTriggeredByDispatch = true;
211-
this.router.navigateByUrl(this.storeState['routerReducer'].state.url);
276+
this.router.navigateByUrl(this.storeState[this.stateKey].state.url);
212277
}
213278
}
214279

yarn.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7873,4 +7873,4 @@ zone.js@^0.8.12:
78737873

78747874
zone.js@^0.8.14:
78757875
version "0.8.18"
7876-
resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.8.18.tgz#8cecb3977fcd1b3090562ff4570e2847e752b48d"
7876+
resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.8.18.tgz#8cecb3977fcd1b3090562ff4570e2847e752b48d"

0 commit comments

Comments
 (0)