5

I have a problem with routing in a master/detail view. If i go to the route /master the InfoComponent should show some general info. And if I go to /master/1 the DetailsComponent should show some data for the item with id 1. In both cases, MasterComponent should show either the selected id or nothing.

I can get this working fairly well. But the problem is that I want to subscribe to the selected :id in OnInit in MasterComponent so that I can highlight it there, something like this:

this.selectedId = this.route.params.map((params: Params) => params["id"])

But that doesn't work since :id is a child route param. And I can't use this.route.firstChild since firstChild will be another route depending on if InfoComponent or DetailsComponent is showing.

Can I get an observable (of :id) that changes when MasterComponent changes between showing the two child components?

This is my routing module:

@NgModule({
    imports: [
        RouterModule.forChild([
            {
                path: "master",
                canActivate: [AuthenticationGuardService],
                children: [
                    {
                        path: "",
                        component: MasterComponent,
                        children: [
                            {
                                path: "",
                                component: InfoComponent
                            },
                            {
                                path: ":id",
                                component: DetailsComponent
                            }
                        ]
                    }
                ]
            }
        ])
    ],
    exports: [
        RouterModule
    ]
})
export class MyRoutingModule { }

So what I would like is to do something like:

this.selectedId = this.route.params.map((params: Params) => params["id"])

Where this.selectedId is an Observable that has the value 1 if the route is /master/1 or the value null if the route is /master.

Joel
  • 8,502
  • 11
  • 66
  • 115

1 Answers1

1

Either

this.route.firstChild.params.map(...)

or use a shared service to communicate the params changes from the child to the parent. See https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-service for examples.

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • Ok. Yeah, `firstChild` doesnt really work, since it will be different depending on which of the child components that are active. I was hoping that I would somehow be able to subscribe to changes when the url changes from `/master/1` to `/master` in the `MasterComponent`. So I can't really do that without involving logic in the child components? That's a bummer... :/ – Joel Nov 01 '16 at 10:14
  • You can get the information from `firstChild` what component is actually add it and ignore the param changes for components you're not interested in. – Günter Zöchbauer Nov 01 '16 at 10:18
  • 1
    I'll set up a plunker to describe what I mean :) – Joel Nov 01 '16 at 10:21
  • This official plunker from the angular.io guide to routing is actually quite descriptive. http://plnkr.co/edit/?p=preview. In `CrisisListComponent` they do `this.route.params.forEach` but that will never contain a value for `params["id"], even if the initial URL is `/crisis-center/1` (which is a bit hard to test through the plunker though). Should this be considered a bug in the router or should `params["id"]` only be accessible from the component that matches that url..? – Joel Nov 01 '16 at 12:22
  • 1
    I have edited that plunker: http://plnkr.co/edit/4eijIs62dyDyI6LkJZZl?p=preview. Here I subscribe to `firstChild` instead to update `selectedId`. It doesn't work since in `ngOnInit` the first child is the `CrisisCenterHomeComponent`. It would work if I could have navigated directly to '/crisis-center/1` (which I don't know how to do in a plunker..) Do you see what I mean? – Joel Nov 01 '16 at 12:29
  • 1
    This might work for you http://plnkr.co/edit/EZv0Xm7BkFyPs61MFeNv?p=preview (my code changes are in the constructor of `app/crisis-center/crisis-list.component.ts` only) – Günter Zöchbauer Nov 02 '16 at 06:48
  • Ok. Yes, that might be what I have to do then. The problem with that is that I get all router events, application wide, but that should be easy to fix by using a more strict check in the `if`. Thank you! – Joel Nov 02 '16 at 07:14
  • 1
    You can use `filter()` to get nicer code http://stackoverflow.com/questions/33520043/how-to-detect-route-change-in-angular-2/38080657#38080657 – Günter Zöchbauer Nov 02 '16 at 07:16