Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2: How to pass route parameters to subroute?

Using Angular 2 rc.1 and TypeScript. I'm having a lot of trouble passing routing parameters to my component when the component is loaded in a subroute. I use the @angular/router-deprecated package.

In my root component, I configured the routes as such:

@RouteConfig([
  {path:'/top', name:'Top', component: EndPointComponent},
  {path:'/sub/...', name:'Sub', component: MiddleManComponent}
])

Here is the endpoint component where I attempt to read the parameters

import {Component} from '@angular/core';
import {RouteParams} from '@angular/router-deprecated';
@Component({
    template: 'Route Params: {{routeParams.params | json}}'
})
export class EndPointComponent{
    constructor(private routeParams:RouteParams){}
}

Here is the middleman component with the subroute to EndPointComponent

import {Component} from '@angular/core';
import {RouteConfig, ROUTER_DIRECTIVES} from '@angular/router-deprecated';
import {EndPointComponent} from "./endpoint.component";

@Component({
    directives: [ROUTER_DIRECTIVES]
    template: `<router-outlet></router-outlet>`
})
@RouteConfig([
    {path: '/end', name: 'End', component: EndPointComponent, useAsDefault: true}
])
export class MiddleManComponent {}

The parameters can be successfully read from the routeParams object of EndPointComponent when the component is loaded from the top-level route (eg: the route named 'Top' in the root component). However, the parameters are always empty when I navigate to EndPointComponent by going throug MiddleManComponent (eg: via the route named 'Sub' in the root component).

Do children routers scrub the parameters from parents before resolving the routes? That doesn't make much sense so I bet I'm missing something. My question is simply: how do I pass route parameters to a subroute?

PS: I tried to build a plunker to demo this setup but I gave up when I couldn't figure out why the application doesn't load.

like image 612
BeetleJuice Avatar asked May 24 '16 02:05

BeetleJuice


2 Answers

Child routes actually get their own instance of RouteParams, distinct from the parent route's. This is done to avoid naming collisions and facilitate encapsulation of the routed component.

One way you can share a parent route's parameters with a component loaded by a child route is through a service.

@Injectable()
export class RouteParamService {
  constructor(private routeParams: RouteParams) {}

  get params() {
    return this.routeParams.params;
  }
}

@Component({
    template: 'Route Params: {{routeParams.params | json}}'
})
export class EndPointComponent{
    constructor(private routeParams:RouteParamService){}
}

@Component({
  directives: [ROUTER_DIRECTIVES]
  template: `<router-outlet></router-outlet>`,
  providers: [RouteParamService]
})
@RouteConfig([
  {path: '/end', name: 'End', component: EndPointComponent, useAsDefault: true}
])
class MiddleManComponent() { }

The RouteParamService will be instantiated at the same route level as the MiddleManComponent and so will get the same instance of RouteParams. When your service gets injected into your child route component, you'll be able to access the parent route params.

If you need 2 instances of EndPointComponent to load at different route tree levels, you'll need another tier of parent route, I think; i.e. a routed component that encapsulates both MiddleManComponent and EndPointComponent, between RootComponent.

RootComponent is not routed, so you won't be able to instantiate RouteParams for the RouteParamService from it. RouteParams is provided by the <router-outlet> component.

like image 96
awiseman Avatar answered Oct 04 '22 03:10

awiseman


Using @angular/[email protected], you can access the parent ActivatedRoute with

export class ChildComponent implements OnInit {

  parentRouteId: string;

  constructor(private route: ActivatedRoute) {
  }

  ngOnInit() {
    this.route.parent.params
      .subscribe((params: Params) => this.parentRouteId = params['id']);
  }
}
like image 28
Alexis Avatar answered Oct 04 '22 03:10

Alexis