Can you use @ViewChild() or similar with a router-outlet? How if so?

Methodician picture Methodician · Aug 31, 2016 · Viewed 10.5k times · Source

I repeatedly run into a situation where I'd like to access a child component existing on the other side of a router outlet rather than a selector:

Like:
<router-outlet></router-outlet>

NOT:
<selector-name></selector-name>

This conflicts with the ViewChild functionality as I know it, yet it seems like my component should be able to see and interact with what's inside that router-outlet just as easily as with what's inside a selector-tag.

For instance I tried this:

export class RequestItemCatsComp {
    @ViewChild('child') child: RequestItemsComp;
    ***etc...***
ngAfterViewInit() {
    if (this.child) // Always child is undefined
        this.groupId = this.child.groupId;
    }
}

But naturally, child is undefined because this is the wrong way. Is there a right way?

I'm trying to use a service to share the data but then run into another problem "expression has changed after it was checked" which I'm hoping to remedy without a hack or enabling prod mode.

Answer

Madhu Ranjan picture Madhu Ranjan · Aug 31, 2016

You may tap into activate event to get reference of instantiated component inside the router outlet.

excerpt from RouterOutlet Docs

A router outlet will emit an activate event any time a new component is being instantiated, and a deactivate event when it is being destroyed.

example

 @Component({
  selector: 'my-app',
  template: `<h3 class="title">Basic Angular 2</h3>
  <router-outlet (activate)="onActivate($event)" ></router-outlet>
  `
})
export class AppComponent {
  constructor(){}

  onActivate(componentRef){
    componentRef.sayhello();
  }
}

@Component({
  selector: 'my-app',
  template: `<h3 class="title">Dashboard</h3>
  `
})
export class DashboardComponent {
  constructor(){}

  sayhello(){
    console.log('hello!!');
  }
}

Here is the Plunker!!

Hope this helps!!