Angular2 Get router params outside of router-outlet

This solution worked for me: complete example.

constructor(
  private readonly router: Router,
  private readonly rootRoute: ActivatedRoute,
){
  router.events.pipe(
    filter(e => e instanceof NavigationEnd),
    map(e => this.getParams(this.rootRoute))
  ).subscribe(params => {
   //
  });
}

private getParams(route: ActivatedRoute): Params {
  // route param names (eg /a/:personId) must be ditinct within
  // a route otherwise they'll be overwritten
  let params = route.snapshot.params
  params = { ...route.snapshot.queryParams, ...params}
  if(route.children){
    for(let r of route.children){
      params = {...this.getParams(r), ...params};        
    }
  }
  return params;
}

Credits to Toxicable.


Is it only possible to access route params in a component rendered by a router-outlet?

Yes, the <router-outlet></router-outlet> tells Angular2 to treat the containing component as a "routing" component. Therefore you cannot get a RouteParams instance injected into the class as it wasn't instantiated via the routing directive.

If not, then what am I doing wrong?

I wouldn't say you're doing anything wrong, you simply had a misconception on how it was designed. I too has this initial misconception. I found this Angular2 article to be a great source for understanding how to pass data around and how to communicate betwixt parent and child components.


In your specific case I'd suggest removing the RouteParams from the constructor of the ContentTreeComponent as it will only be available if rendered from a "routing" component.
export class ContentTreeComponent implements OnInit {

    constructor(
        private _contentService: ContentService,
        private _router: Router
    ) { }

    // Omitted for brevity...
}

Then in order to get the id, you'd probably have to share a bit more of your top-level code so that I can see where it is coming from...


Get the active route from outside a component in angular 2.1.0 and Router 3.1.0

I found a nice way to get all params, queryParmas, segments and fragments from the displayed route from anywhere inside your App. Just add this Code to any Component where you need it, or create a Service that can be injected throughout your App.

import { Router, NavigationEnd } from "@angular/router";
import { Component, OnInit } from '@angular/core';

...

export class MyComponentOrService implements OnInit {

constructor(private router: Router) {}

ngOnInit() {

  /* this subscription will fire always when the url changes */
  this.router.events.subscribe(val=> {

    /* the router will fire multiple events */
    /* we only want to react if it's the final active route */
    if (val instanceof NavigationEnd) {

     /* the variable curUrlTree holds all params, queryParams, segments and fragments from the current (active) route */
     let curUrlTree = this.router.parseUrl(this.router.url);
     console.info(curUrlTree);
    }
  });
}
...

In the new router (>= RC.0 <=RC.2) this would be

  import 'rxjs/add/operator/first';
  ...

  constructor(private router:Router, private routeSerializer:RouterUrlSerializer, private location:Location) {
    router.changes.first().subscribe(() => {

    let urlTree = this.routeSerializer.parse(location.path());
      console.log('id', urlTree.children(urlTree.children(urlTree.root)[0])[0].segment);
    });
  }

See also Angular 2 RC1: Get parameters from the initial URL used