How to get :id param of child route from parent component in Angular2

36.6k Views Asked by At

I'm trying to get the :id param defined in

RouterModule.forRoot([
  {
    path: 'orders',
    component: ListComponent,
    children: [
      {
        path: 'view/:id',
        component: ViewComponent
      },
    ]
  }
])

from ListComponent.

I already tried:

route: ActivatedRoute

route.params.subscribe(params => {
  let id = +params['id'];
})

from ListComponent, but the params array is empty, I suppose it's because the :id param belongs to ViewComponent not ListComponent.

How can I get the id param in ListComponent?

5

There are 5 best solutions below

13
On BEST ANSWER

You can use the firstChild property or the ActivatedRoute to get the child route:

route.firstChild.snapshot.params['id']
1
On

To get the child's params inside the parent component, i used the firstChild property of ActivatedRoute, because i only have on child route

route: ActivatedRoute

route.firstChild.params.subscribe(params => {
  let id = +params['id'];
});
2
On

Recursively finding child params wont always get you the params you are looking for. Specially when moving routes around.

Instead, an RxJS ReplaySubject can be used to publish the current child id.

Create a new service:

@Injectable()
export class ChildIdService  {
  current$ = new ReplaySubject<number>();
}

Import it on the child component and subscribe to the replay subject:

export class ChildComponent implements OnInit {
  constructor(private ar: ActivatedRoute, public ci: ChildIdService){}

  ngOnInit(){
    this.ar.params.map(params => +params.id).subscribe(this.ci.current$);
  }
}

Import the service on the parent component and use the async pipe to subscribe to the child value:

<span>Mother component child ID: {{ci.current$ | async}}</span>

Here is a working snippet: https://stackblitz.com/edit/angular-b8xome (add /child/42 to the browser app preview to see it working)


Alternatively define the components as siblings and add the parent as a componentless route, ex.: https://vsavkin.com/the-powerful-url-matching-engine-of-angular-router-775dad593b03 under "Sibling Components Using Same Data"

0
On

You can keep digging through the route.firstChild.params['id'] if there is just the one child route or use something like route.children[0].children[1].params['id'] to dig through multiple levels using bracket notation to access sibling routes. Its a bit of trial and error when it comes to finding the correct level.

0
On

another way of doing this is adding the following in the parent component:

<ng-container *ngIf="routerOutlet.isActivated && routerOutlet.activatedRoute?.paramMap | async as paramMap">
child id is: {{paramMap.get('id')}}!
</ng-container>

<router-outlet #routerOutlet="outlet"></router-outlet>

of course, it would be nicer to use have resolver at the child instead of params

<ng-container *ngIf="routerOutlet.activatedRouteData['child'] as child">
child id is : {{child.id}}
</ng-container>

<router-outlet #routerOutlet="outlet"></router-outlet>

assuming child route has something like:

// ...
resolve: {
 child: 'childResolver',
},

and the child resolver can be in some module:

// ...
providers: [{
    provide: 'childResolver',
    useValue: (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => ({
      id: route.paramMap.get('id')
    })
  }],