From 72bca5477896640dc1304614444114d41a010e9c Mon Sep 17 00:00:00 2001 From: markostanimirovic Date: Wed, 9 Dec 2020 21:43:50 +0100 Subject: [PATCH] feat(router-store) add selectParamFromRouterTree selector --- .../spec/router_selectors.spec.ts | 19 +++++++++++++++++-- modules/router-store/src/models.ts | 3 +++ modules/router-store/src/router_selectors.ts | 16 ++++++++++++++++ .../content/guide/router-store/selectors.md | 17 +++++++++-------- 4 files changed, 45 insertions(+), 10 deletions(-) diff --git a/modules/router-store/spec/router_selectors.spec.ts b/modules/router-store/spec/router_selectors.spec.ts index 1a80b8ee24..52709e1d8e 100644 --- a/modules/router-store/spec/router_selectors.spec.ts +++ b/modules/router-store/spec/router_selectors.spec.ts @@ -18,9 +18,13 @@ const mockData = { }, fragment: null, firstChild: { - params: {}, + params: { + p: 'first-occurrence', + }, paramMap: { - params: {}, + params: { + p: 'first-occurrence', + }, }, data: {}, url: [ @@ -42,10 +46,12 @@ const mockData = { firstChild: { params: { id: 'etyDDwAAQBAJ', + p: 'second-occurrence', }, paramMap: { params: { id: 'etyDDwAAQBAJ', + p: 'second-occurrence', }, }, data: { @@ -182,6 +188,15 @@ describe('Router State Selectors', () => { ); }); + it('should create a selector for selecting the first occurrence of a specific route param', () => { + const result = selectors.selectParamFromRouterTree('p')(state); + + expect(result).toEqual(state.router.state.root.firstChild.params.p); + expect(result).not.toEqual( + state.router.state.root.firstChild.firstChild.params.p + ); + }); + it('should create a selector for selecting the route data', () => { const result = selectors.selectRouteData(state); diff --git a/modules/router-store/src/models.ts b/modules/router-store/src/models.ts index 2acdcc4018..9a642d2030 100644 --- a/modules/router-store/src/models.ts +++ b/modules/router-store/src/models.ts @@ -8,6 +8,9 @@ export interface RouterStateSelectors { selectQueryParam: (param: string) => MemoizedSelector; selectRouteParams: MemoizedSelector; selectRouteParam: (param: string) => MemoizedSelector; + selectParamFromRouterTree: ( + param: string + ) => MemoizedSelector; selectRouteData: MemoizedSelector; selectUrl: MemoizedSelector; } diff --git a/modules/router-store/src/router_selectors.ts b/modules/router-store/src/router_selectors.ts index 362877cb80..06edc18896 100644 --- a/modules/router-store/src/router_selectors.ts +++ b/modules/router-store/src/router_selectors.ts @@ -45,6 +45,21 @@ export function getSelectors( selectCurrentRoute, (route) => route && route.data ); + const selectParamFromRouterTree = (param: string) => + createSelector(selectRouterState, (routerState) => { + let paramValue: string | undefined; + let route = routerState?.root; + + while (route?.firstChild) { + route = route.firstChild; + if (route?.params?.[param]) { + paramValue = route.params[param]; + break; + } + } + + return paramValue; + }); const selectUrl = createSelector( selectRouterState, (routerState) => routerState && routerState.url @@ -57,6 +72,7 @@ export function getSelectors( selectQueryParam, selectRouteParams, selectRouteParam, + selectParamFromRouterTree, selectRouteData, selectUrl, }; diff --git a/projects/ngrx.io/content/guide/router-store/selectors.md b/projects/ngrx.io/content/guide/router-store/selectors.md index ca0f7adc60..ea014b59fe 100644 --- a/projects/ngrx.io/content/guide/router-store/selectors.md +++ b/projects/ngrx.io/content/guide/router-store/selectors.md @@ -25,14 +25,15 @@ export const selectRouter = createFeatureSelector< >('router'); export const { - selectCurrentRoute, // select the current route - selectFragment, // select the current route fragment - selectQueryParams, // select the current route query params - selectQueryParam, // factory function to select a query param - selectRouteParams, // select the current route params - selectRouteParam, // factory function to select a route param - selectRouteData, // select the current route data - selectUrl, // select the current url + selectCurrentRoute, // select the current route + selectFragment, // select the current route fragment + selectQueryParams, // select the current route query params + selectQueryParam, // factory function to select a query param + selectRouteParams, // select the current route params + selectRouteParam, // factory function to select a route param + selectParamFromRouterTree, // factory function to select the first occurrence of a route param + selectRouteData, // select the current route data + selectUrl, // select the current url } = fromRouter.getSelectors(selectRouter); export const selectSelectedCarId = selectQueryParam('carId');