diff --git a/modules/router-store/spec/integration.spec.ts b/modules/router-store/spec/integration.spec.ts index 9ab525d2f2..d990187b24 100644 --- a/modules/router-store/spec/integration.spec.ts +++ b/modules/router-store/spec/integration.spec.ts @@ -393,7 +393,10 @@ describe('integration spec', () => { }); }); - it('should support a custom RouterStateSnapshot serializer ', (done: any) => { + function shouldSupportCustomSerializer( + serializerThroughConfig: boolean, + done: Function + ) { interface SerializedState { url: string; params: any; @@ -422,11 +425,17 @@ describe('integration spec', () => { } } - const providers = [ - { provide: RouterStateSerializer, useClass: CustomSerializer }, - ]; - - createTestModule({ reducers: { routerReducer, reducer }, providers }); + if (serializerThroughConfig) { + createTestModule({ + reducers: { routerReducer, reducer }, + config: { serializer: CustomSerializer }, + }); + } else { + const providers = [ + { provide: RouterStateSerializer, useClass: CustomSerializer }, + ]; + createTestModule({ reducers: { routerReducer, reducer }, providers }); + } const router = TestBed.get(Router); const log = logOfRouterAndActionsAndStore(); @@ -464,6 +473,14 @@ describe('integration spec', () => { log.splice(0); done(); }); + } + + it('should support a custom RouterStateSnapshot serializer via provider', (done: any) => { + shouldSupportCustomSerializer(false, done); + }); + + it('should support a custom RouterStateSnapshot serializer via config', (done: any) => { + shouldSupportCustomSerializer(true, done); }); it('should support event during an async canActivate guard', (done: any) => { diff --git a/modules/router-store/src/router_store_module.ts b/modules/router-store/src/router_store_module.ts index 2211eacd04..4c6a2a4555 100644 --- a/modules/router-store/src/router_store_module.ts +++ b/modules/router-store/src/router_store_module.ts @@ -18,6 +18,7 @@ import { DefaultRouterStateSerializer, RouterStateSerializer, SerializedRouterStateSnapshot, + RouterState, } from './serializer'; /** @@ -146,14 +147,6 @@ export type RouterAction< | RouterErrorAction | RouterNavigatedAction; -/** - * Simple router state. - * All custom router states should have at least this property. - */ -export type RouterState = { - url: string; -}; - export type RouterReducerState< T extends RouterState = SerializedRouterStateSnapshot > = { @@ -182,6 +175,7 @@ export function routerReducer< export interface StoreRouterConfig { stateKey?: string; + serializer?: new () => RouterStateSerializer; } export const _ROUTER_CONFIG = new InjectionToken( @@ -192,7 +186,7 @@ export const ROUTER_CONFIG = new InjectionToken( ); export const DEFAULT_ROUTER_FEATURENAME = 'routerReducer'; -export function _createDefaultRouterConfig( +export function _createRouterConfig( config: StoreRouterConfig | StoreRouterConfigFunction ): StoreRouterConfig { let _config: StoreRouterConfig; @@ -205,10 +199,19 @@ export function _createDefaultRouterConfig( return { stateKey: DEFAULT_ROUTER_FEATURENAME, + serializer: DefaultRouterStateSerializer, ..._config, }; } +export function _createSerializer( + config: StoreRouterConfig +): RouterStateSerializer { + // This function gets handed a complete config-object from _createRouterConfig, + // so we know the serializer property exists + return new config.serializer!(); +} + export type StoreRouterConfigFunction = () => StoreRouterConfig; enum RouterTrigger { @@ -261,16 +264,23 @@ enum RouterTrigger { */ @NgModule({ providers: [ - { provide: RouterStateSerializer, useClass: DefaultRouterStateSerializer }, { provide: _ROUTER_CONFIG, - useValue: { stateKey: DEFAULT_ROUTER_FEATURENAME }, + useValue: { + stateKey: DEFAULT_ROUTER_FEATURENAME, + serializer: DefaultRouterStateSerializer, + }, }, { provide: ROUTER_CONFIG, - useFactory: _createDefaultRouterConfig, + useFactory: _createRouterConfig, deps: [_ROUTER_CONFIG], }, + { + provide: RouterStateSerializer, + deps: [ROUTER_CONFIG], + useFactory: _createSerializer, + }, ], }) export class StoreRouterConnectingModule { @@ -282,14 +292,7 @@ export class StoreRouterConnectingModule { ): ModuleWithProviders { return { ngModule: StoreRouterConnectingModule, - providers: [ - { provide: _ROUTER_CONFIG, useValue: config }, - { - provide: ROUTER_CONFIG, - useFactory: _createDefaultRouterConfig, - deps: [_ROUTER_CONFIG], - }, - ], + providers: [{ provide: _ROUTER_CONFIG, useValue: config }], }; } diff --git a/modules/router-store/src/serializer.ts b/modules/router-store/src/serializer.ts index 9d7f9bedc4..c9fdaee011 100644 --- a/modules/router-store/src/serializer.ts +++ b/modules/router-store/src/serializer.ts @@ -1,10 +1,18 @@ import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; -export abstract class RouterStateSerializer { +/** + * Simple router state. + * All custom router states / state serializers should have at least this property. + */ +export interface RouterState { + url: string; +} + +export abstract class RouterStateSerializer { abstract serialize(routerState: RouterStateSnapshot): T; } -export interface SerializedRouterStateSnapshot { +export interface SerializedRouterStateSnapshot extends RouterState { root: ActivatedRouteSnapshot; url: string; }