NgRx Course – NgRx Router Store

In the previous video, we finished our sample application. But there is one more thing that we should cover in this course, and that’s the router-store library.

The router-store binds the Angular router to NgRx. This enables us to trace where we are in the application and save the route. The route parameters and the query parameters in the store.

For that, we’re going to add a CustomSerializer. So let’s create a util.ts file inside a shared folder. We’re going to copy the code from the router store documentation:

// shared/utils.ts
import { StoreModule, ActionReducerMap } from '@ngrx/store';
import { Params, RouterStateSnapshot } from '@angular/router';
import {
  StoreRouterConnectingModule,
  routerReducer,
  RouterReducerState,
  RouterStateSerializer,
} from '@ngrx/router-store';

export interface RouterStateUrl {
  url: string;
  params: Params;
  queryParams: Params;
}

export interface State {
  router: RouterReducerState<RouterStateUrl>;
}

@Injectable()
export class CustomSerializer implements RouterStateSerializer<RouterStateUrl> {
  serialize(routerState: RouterStateSnapshot): RouterStateUrl {
    let route = routerState.root;

    while (route.firstChild) {
      route = route.firstChild;
    }

    const {
      url,
      root: { queryParams },
    } = routerState;
    const { params } = route;

    // Only return an object including the URL, params and query params
    // instead of the entire snapshot
    return { url, params, queryParams };
  }
}

export const reducers: ActionReducerMap<State> = {
  router: routerReducer,
};

(https://github.com/ngrx/platform/blob/master/docs/router-store/api.md#custom-router-state-serializer)

Once we have the first part of the code in the utils file, we can then go and register it in the app.module.ts file:

// app.module.ts
import { BrowserModule } from "@angular/platform-browser";
import { NgModule } from "@angular/core";
import { HttpClientModule } from "@angular/common/http";

// NgRx
import { StoreModule } from "@ngrx/store";
import { EffectsModule } from "@ngrx/effects";
import {
  StoreRouterConnectingModule,
  routerReducer,
  RouterStateSerializer
} from "@ngrx/router-store";
import { CustomSerializer } from "./shared/utils";

import { AppComponent } from "./app.component";
import { HomeComponent } from "./home/home.component";
import { NavbarComponent } from "./navbar/navbar.component";
import { AppRoutingModule } from "./app-routing.module";

import { StoreDevtoolsModule } from "@ngrx/store-devtools";

@NgModule({
  declarations: [AppComponent, HomeComponent, NavbarComponent],
  imports: [
    BrowserModule,
    StoreModule.forRoot({
      router: routerReducer
    }),
    StoreRouterConnectingModule.forRoot({ stateKey: "router" }), 
    router state in our state tree
    StoreDevtoolsModule.instrument(),
    EffectsModule.forRoot([]),
    AppRoutingModule,
    HttpClientModule
  ],
  providers: [{ provide: RouterStateSerializer, useClass: CustomSerializer }],
  bootstrap: [AppComponent]
})
export class AppModule {}

At this stage, we import the CustomSerializer. We do this by passing the routerReducer to the StoreModule.forRoot(), as it’s part of the root state of the application. Then we specify “router” as the StateKey. That will be the name of the router state in our state tree.

Now, if we refresh the page we’ll see that the router state has been added to the store.

There are several cases where you might need to use the store-router. But we’re not going to look at it in-depth in this video. This was just the initial setup for our sample application. For more information, please visit and review the official documentation.