[Angular2] Access router-inserted component instance?

885 views
Skip to first unread message

Chris Derossi

unread,
Jan 24, 2016, 9:11:09 PM1/24/16
to AngularJS
I want to be able to communicate (i.e. call methods) between a component instance and one of its child component instances. Or just as good for me, call from one component instance to the parent component instance.

For example, take this pseudo setup:

@Component({
    selector
: 'outerC',
   
template: `
        <div>stuff</div>
        <router-outlet></router-outlet>
    `
,
    directives
: [ROUTER_DIRECTIVES]
})
@RouteConfig([
   
{path:'/',        name: 'ItemList',   component: ItemListComponent, useAsDefault: true},
   
{path:'/:id',     name: 'ItemDetail', component: ItemDetailComponent},
])
export class OuterComponent
{
    constructor
( ) { }
}

@Component({
    selector
: 'item-list',
   
template: `<div>stuff</div>`
})
export class ItemListComponent
{
    constructor
( ) { }
    something
() { return x; }
}

@Component({
    selector
: 'item-detail',
   
template: `<div>stuff</div>`
})
export class ItemDetailComponent
{
    constructor
( ) { }
    something
() { return x; }
}

I'd like the code in OuterComponent to be able to call the something() method on whichever component instance that the router inserts at the router-outlet location. Or, conversely and more generally, I'd like code in ItemListComponent or ItemDetailComponent to be able to call methods on the OuterComponent instance that is hosting them.

Is there a "right" way for these instances to get references to each other? It doesn't look like there's an interface on Router to let OuterComponent find out what the Router has inserted at the router-outlet.

I've looked at the ViewQuery stuff and I can sorta make it work. But it requires that I code specifically for the class names that I'm looking for. As my RouteConfig evolves and gets lengthy, I dislike the idea that I'd have to manually keep a parallel list of the possible components in my Query.

Any ideas, or feedback about why I'm looking at this the wrong way?

Thanks!

Günter Zöchbauer

unread,
Jan 26, 2016, 7:15:01 AM1/26/16
to AngularJS
Communication between parent and child work well with just binding. Otherwise use a shared service

Chris Derossi

unread,
Jan 29, 2016, 7:12:09 PM1/29/16
to AngularJS
Thanks for the pointer.

From what I understand (and I'm just learning), it's not possible to use simple binding between a parent and a child inserted by the router. My view only contains <router-outlet> and any one of several components may occupy it as the user navigates around.

What I wound up doing was creating a tiny service shared by all relevant components and all it does is allow them to find each other. The service just has a public property parent_service and my parent component's constructor just does:

_simpleservice.parent_service = this;

And my child components just do:

_simpleservice.parent_service.someMethod();

It was very simple to code this up, but seems like a roundabout way to discover the parent/child relationships as the router changes them.

Günter Zöchbauer

unread,
Jan 30, 2016, 9:17:36 AM1/30/16
to AngularJS
I haven't played with router much myself but from what I have seen binding can't be used with components added by the router.

Instead of

    simpleservice.parent_service = this;

I'd prefer to add an EventEmitter to the service and subscribe to it

   simpleservice.someEmitter.subscribe(value => {
     this.someMethod();
   }) 

and in the other component to invoke `someMethod()`

   simpleservice.someEmitter.next(someValue);


to avoid to tight coupling between components, for example to not make testing too hard.
Reply all
Reply to author
Forward
0 new messages