-
-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(router-store): add selectors for router state (#1874)
Closes #1854
- Loading branch information
1 parent
d5e3c0c
commit 21c67cc
Showing
6 changed files
with
260 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
import { RouterReducerState, getSelectors } from '@ngrx/router-store'; | ||
import { RouterStateSelectors } from '../src/models'; | ||
|
||
const mockData = { | ||
state: { | ||
root: { | ||
params: {}, | ||
paramMap: { | ||
params: {}, | ||
}, | ||
data: {}, | ||
url: [], | ||
outlet: 'primary', | ||
routeConfig: null, | ||
queryParams: {}, | ||
queryParamMap: { | ||
params: {}, | ||
}, | ||
fragment: null, | ||
firstChild: { | ||
params: {}, | ||
paramMap: { | ||
params: {}, | ||
}, | ||
data: {}, | ||
url: [ | ||
{ | ||
path: 'login', | ||
parameters: {}, | ||
}, | ||
], | ||
outlet: 'primary', | ||
routeConfig: { | ||
path: 'login', | ||
}, | ||
queryParams: { | ||
id: 3, | ||
}, | ||
queryParamMap: { | ||
params: {}, | ||
}, | ||
firstChild: { | ||
params: { | ||
id: 'etyDDwAAQBAJ', | ||
}, | ||
paramMap: { | ||
params: { | ||
id: 'etyDDwAAQBAJ', | ||
}, | ||
}, | ||
data: { | ||
testData: 'test-data', | ||
}, | ||
url: [ | ||
{ | ||
path: 'etyDDwAAQBAJ', | ||
parameters: {}, | ||
}, | ||
], | ||
outlet: 'primary', | ||
routeConfig: { | ||
path: ':id', | ||
}, | ||
queryParams: {}, | ||
queryParamMap: { | ||
params: {}, | ||
}, | ||
children: [], | ||
}, | ||
fragment: null, | ||
children: [], | ||
}, | ||
children: [ | ||
{ | ||
params: {}, | ||
paramMap: { | ||
params: {}, | ||
}, | ||
data: {}, | ||
url: [ | ||
{ | ||
path: 'login', | ||
parameters: {}, | ||
}, | ||
], | ||
outlet: 'primary', | ||
routeConfig: { | ||
path: 'login', | ||
}, | ||
queryParams: {}, | ||
queryParamMap: { | ||
params: {}, | ||
}, | ||
children: [], | ||
}, | ||
], | ||
}, | ||
url: '/login', | ||
}, | ||
navigationId: 1, | ||
}; | ||
describe('Router State Selectors', () => { | ||
describe('Composed Selectors', () => { | ||
interface State { | ||
router: RouterReducerState<any>; | ||
} | ||
|
||
let selectors: RouterStateSelectors<State>; | ||
let state: State; | ||
|
||
beforeEach(() => { | ||
state = { | ||
router: mockData, | ||
}; | ||
|
||
selectors = getSelectors((state: State) => state.router); | ||
}); | ||
it('should create selectCurrentRoute selector for selecting the current route', () => { | ||
const result = selectors.selectCurrentRoute(state); | ||
|
||
expect(result).toEqual(state.router.state.root.firstChild.firstChild); | ||
}); | ||
it('should return undefined from selectCurrentRoute if routerState does not exist', () => { | ||
interface State { | ||
router: any; | ||
} | ||
let state: State; | ||
state = { | ||
router: undefined, | ||
}; | ||
selectors = getSelectors((state: State) => state.router); | ||
|
||
const result = selectors.selectCurrentRoute(state); | ||
|
||
expect(result).toEqual(undefined); | ||
}); | ||
it('should create a selector for selecting the query params', () => { | ||
const result = selectors.selectQueryParams(state); | ||
|
||
expect(result).toEqual( | ||
state.router.state.root.firstChild.firstChild.queryParams | ||
); | ||
}); | ||
it('should create a selector for selecting the route params', () => { | ||
const result = selectors.selectRouteParams(state); | ||
|
||
expect(result).toEqual( | ||
state.router.state.root.firstChild.firstChild.params | ||
); | ||
}); | ||
it('should create a selector for selecting the route data', () => { | ||
const result = selectors.selectRouteData(state); | ||
|
||
expect(result).toEqual( | ||
state.router.state.root.firstChild.firstChild.data | ||
); | ||
}); | ||
it('should create a selector for selecting the url', () => { | ||
const result = selectors.selectUrl(state); | ||
|
||
expect(result).toEqual(state.router.state.url); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { Data, Params } from '@angular/router'; | ||
|
||
export interface RouterStateSelectors<V> { | ||
selectCurrentRoute: (state: V) => any; | ||
selectQueryParams: (state: V) => Params; | ||
selectRouteParams: (state: V) => Params; | ||
selectRouteData: (state: V) => Data; | ||
selectUrl: (state: V) => string; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import { RouterReducerState } from '@ngrx/router-store'; | ||
import { createSelector } from '@ngrx/store'; | ||
import { RouterStateSelectors } from './models'; | ||
|
||
export function getSelectors<V>( | ||
selectState: (state: V) => RouterReducerState<any> | ||
): RouterStateSelectors<V>; | ||
export function getSelectors<V>( | ||
selectState: (state: V) => RouterReducerState<any> | ||
): RouterStateSelectors<V> { | ||
const selectRouterState = createSelector( | ||
selectState, | ||
router => router && router.state | ||
); | ||
const selectCurrentRoute = createSelector(selectRouterState, routerState => { | ||
if (!routerState) { | ||
return undefined; | ||
} | ||
let route = routerState.root; | ||
while (route.firstChild) { | ||
route = route.firstChild; | ||
} | ||
return route; | ||
}); | ||
const selectQueryParams = createSelector( | ||
selectCurrentRoute, | ||
route => route && route.queryParams | ||
); | ||
const selectRouteParams = createSelector( | ||
selectCurrentRoute, | ||
route => route && route.params | ||
); | ||
const selectRouteData = createSelector( | ||
selectCurrentRoute, | ||
route => route && route.data | ||
); | ||
const selectUrl = createSelector( | ||
selectRouterState, | ||
routerState => routerState && routerState.url | ||
); | ||
|
||
return { | ||
selectCurrentRoute, | ||
selectQueryParams, | ||
selectRouteParams, | ||
selectRouteData, | ||
selectUrl, | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# Router selectors | ||
|
||
The `getSelectors` method supplied within `@ngrx/router-store` provides functions for selecting common information from the router state. | ||
|
||
The `getSelectors` method takes a selector function as its only argument to select the piece of state where the router state is being stored. | ||
The example below shows how to provide a selector for the top level `router` key in your state object. | ||
|
||
**Note:** The `getSelectors` method works with the `routerReducer` provided by `@ngrx/router-store`. If you use a [custom serializer](guide/router-store/configuration#custom-router-state-serializer), you'll need to provide your own selectors. | ||
|
||
Usage: | ||
|
||
`reducers/index.ts` | ||
|
||
```ts | ||
import { getSelectors, RouterReducerState } from '@ngrx/router-store'; | ||
|
||
export interface State { | ||
router: fromRouter.RouterReducerState<any>; | ||
} | ||
|
||
export const selectRouter = createFeatureSelector< | ||
State, | ||
fromRouter.RouterReducerState<any> | ||
>('router'); | ||
|
||
const { | ||
selectQueryParams, // select the current route query params | ||
selectRouteParams, // select the current route params | ||
selectRouteData, // select the current route data | ||
selectUrl, // select the current url | ||
} = getSelectors(selectRouter); | ||
|
||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters