How to set default query params for Route in Angular 7?
In our Angular-7-Application, we use @ngrx and @ngrx/router-store to get the query params into the state.
To have query params and state synchronized you need an effect that captures any action that results in a page change in your application. Inside the event, you'll have something like:
@Effect({dispatch:false})
setRouteParams = this.actions$.pipe(
ofType<ActionCausingPageChange>("action name"),
tap( action =>{
let a = { page: action.payload.page };
// or in case it's not part of action payload, get it from store
this.router.navigate(
[], {
relativeTo: this.route,
queryParamsHandling: 'merge',
queryParams: a
});
}
)
);
Then have a meta reducer to update state from query params on page reload:
export function initStateFromQueryParams(
reducer: ActionReducer<AppState>
): ActionReducer<AppState> {
return function(state, action) {
const newState = reducer(state, action);
if ([INIT.toString(), UPDATE.toString()].includes(action.type)) {
const urlParams = new URLSearchParams(window.location.search);
return { ...newState, page: urlParams.get("page") };
}
return newState;
};
}
This way you always know if page number changes it's gonna be reflected in url consequently. So even if you go to a new route(component) after that route gets its initial data the effect will trigger which updates query params.
You may want to checkout out this phenomenal article about state management in angular apps
Florian Gössele
"We are what we repeatedly do. Excellence, then, is not an act but a habit." - Aristotle
Updated on June 08, 2022Comments
-
Florian Gössele almost 2 years
In our Angular-7-Application, we use @ngrx and @ngrx/router-store to get the query params into the state.
A few components of the application are paginated lists. We have every list as a component and the Pagination-Component included in every list.
The current page is stored in the URL as a query Parameter:
user/:userId/agent?page=0
and the PaginationComponent gets the current page fromstate.router.state.queryParams.page
. However, if a user accesses the URLuser/:userId/agent
,queryParams.page
returns undefined.We could solve this by using
state.router.state.queryParams.page || 0
in every component but I wonder, if there is an easier way - can a Route without query params be redirect to a Route with query params?I tried using the most obvious redirect:
{ path: 'user/:userId/agent', redirectTo: '/user/:userId/agent?page=0', pathMatch: 'full' }, { path: 'user/:userId/agent?page=0', component: AgentListComponent },
but I get
Error: Cannot match any routes. URL Segment: 'user/max/agent'
.The only feature request I found was this one where the error above appears.
-
david_i_smith over 4 yearsThanks for the link to that article. The following made me wonder whether the navigation should take place inside the effect or outside: "Since the user can always interact with the URL directly, we should treat the router as the source of truth and the initiator of actions."