Angular 2 route and route params not visible to all components, use ng-router-state-params service

Error

The Angular 2 router will only update the target component with the url and params. Each component is initialized only when it comes into view. If it already visible when the url changes, it will not be updated by the router. For google, angular 2 components not updating when url changes.

If you’re used to using Angular 1 with ui-router ($state and $stateParams services), using Angular 2 can be frustrating. Instead of using ui-router, we will try to stick with the barebones Angular 2 setup. Angular 2 has its own routing component that has been a huge improvement over the Angular 1 routing component. However, it does not follow the same design as ui-router, which was much easier in my opinion.

The Fix

Install ng-router-state-params as a service provider. The default Router and RouterModule does not provide any access to the active state or state params to all components, only the target component. This service will watch the events of the RouterModule, parse them, and provide them as a value or an observable to any component that needs it.

Example

Install using npm:

npm install ng-router-state-params
 // app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { Router } from '@angular/router';

import { AppComponent } from './app.component';

import { AppRoutingModule } from './app-routing.module';

import { RouterStateParamsService } from 'ng-router-state-params';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    AppRoutingModule,
    BrowserModule,
    HttpModule
  ],
  providers: [
    RouterStateParamsService
  ],
  bootstrap: [AppComponent]
})
export class AppModule {
}
 // app-routing.module.ts
import { NgModule }             from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

const routes: Routes = [
    { path: '', redirectTo: 'dashboard', pathMatch: 'full' },
    {
        path: 'dashboard',
        loadChildren: './dashboard/dashboard.module#DashboardModule',
    },
    {
        path: 'admin',
        loadChildren: './admin/admin.module#AdminModule'
    }
];

@NgModule({
    imports: [ RouterModule.forRoot(routes) ],
    exports: [ RouterModule ]
})

export class AppRoutingModule {}
 // admin/admin-routing.module.ts
import { NgModule }             from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

import { AdminComponent }           from './admin.component';
import { AdminViewComponent }           from './admin-view.component';

const adminRoutes: Routes = [
    {
        path: '',
        component: AdminComponent,
        children: [
            {
                {
                path: ':type',
                component: AdminViewComponent,
                data: {
                    title: 'Admin Page'
                },
                children: [
                    {
                        path: ':id'
                    }
                ]
            }
            }
        ]
    }
];

@NgModule({
    imports: [
        RouterModule.forChild(adminRoutes)
    ],
    exports: [
        RouterModule
    ]
})
 // app.component.html
<top-nav></top-nav>
<router-outlet></router-outlet>
<bottom-nav></bottom-nav>
 // admin/admin.component.html
<a routerLink="/admin/user">Users</a>
<a routerLink="/admin/company">Companies</a>
<router-outlet></router-outlet>

With this setup, we are using the default Angular 2 routing to tell our application which components to load based on the url. On the admin page, the top-nav component will always be visible when switching from /admin/user to /admin/company, so the router will not reload it. Using ng-router-state-params, we can access the route information.

 // top-nav/top-nav.component.html
<a routerLink="/dashboard">Dashboard</a>
<a routerLink="/admin">Admin</a>
current url: {{routerStateParamsService.getUrl()}}
 // top-nav/top-nav.component.ts
import { Component, OnInit } from '@angular/core';

import { RouterStateParamsService }  from 'ng-router-state-params';

@Component({
  selector: 'top-nav',
  templateUrl: './top-nav.component.html',
  styleUrls: ['./top-nav.component.scss']
})
export class TopNavComponent implements OnInit {

  constructor(public routerStateParamsService: RouterStateParamsService) { }

  ngOnInit() {
    this.routerStateParamsService.getParams().subscribe( val => {
      console.log("top nav params", val);
    });

    this.routerStateParamsService.getUrl().subscribe( val => {
      console.log("top nav url", val);
    });

    this.routerStateParamsService.getConfig().subscribe( val => {
      console.log("top nav config", val);
    });

    this.routerStateParamsService.getRoute().subscribe( val => {
      console.log("top nav route", val);
    });
  }

}

Now we have access and can subscribe to route changes in our top-nav component. This is useful for setting the page title, showing breadcrumbs, modifying the menu based on what’s visible below.

ng-router-state-params Angular 4 router state params service

github: https://github.com/stomo21/ng-router-state-params

npm: https://www.npmjs.com/package/ng-router-state-params

Share this:

Leave a comment