BeetleJuice
BeetleJuice

Reputation: 40946

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.

Upvotes: 5

Views: 7177

Answers (4)

Alexis
Alexis

Reputation: 33

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']);
  }
}

Upvotes: 3

mrgoos
mrgoos

Reputation: 1316

You can inject ActivatedRote and take a snapshot, even easier:

constructor(private route: ActivatedRoute) {}; ngOnInit() { console.log('one of my parents route param:', this.route.snapshot.parent.params['PARAM-NAME']); }

Upvotes: 0

F&#225;bio Junqueira
F&#225;bio Junqueira

Reputation: 2781

Using the "@angular/router": "3.0.0-alpha.6" package, i was able to get the parent route argument by doing the following:

export class ChildComponent {

    private sub: any;

    private parentRouteId: number;

    constructor(
        private router: Router,
        private route: ActivatedRoute) {
    }

    ngOnInit() {
        this.sub = this.router.routerState.parent(this.route).params.subscribe(params => {
            this.parentRouteId = +params["id"];
        });
    }

    ngOnDestroy() {
        this.sub.unsubscribe();
    }
}

In this example the route has the following format: /parent/:id/child/:childid

export const routes: RouterConfig = [
    {
        path: '/parent/:id',
        component: ParentComponent,
        children: [
            { path: '/child/:childid', component: ChildComponent }]
    }
];

Upvotes: 1

awiseman
awiseman

Reputation: 5724

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.

Upvotes: 4

Related Questions