Passing data into "router-outlet" child components

Zack picture Zack · Jan 3, 2017 · Viewed 97.1k times · Source

I've got a parent component that goes to the server and fetches an object:

// parent component

@Component({
    selector : 'node-display',
    template : `
        <router-outlet [node]="node"></router-outlet>
    `
})

export class NodeDisplayComponent implements OnInit {

    node: Node;

    ngOnInit(): void {
        this.nodeService.getNode(path)
            .subscribe(
                node => {
                    this.node = node;
                },
                err => {
                    console.log(err);
                }
            );
    }

And in one of several childdren display:

export class ChildDisplay implements OnInit{

    @Input()
    node: Node;

    ngOnInit(): void {
        console.log(this.node);
    }

}

It doesn't seem I can just inject data into the router-outlet. It looks like I get the error in the web console:

Can't bind to 'node' since it isn't a known property of 'router-outlet'.

This somewhat makes sense, but how would I do the following:

  1. Grab the "node" data from the server, from within the parent component?
  2. Pass the data I have retrieved from the server into the child router-outlet?

It doesn't seem like router-outlets work the same way.

Answer

G&#252;nter Z&#246;chbauer picture Günter Zöchbauer · Jan 3, 2017
<router-outlet [node]="..."></router-outlet> 

is just invalid. The component added by the router is added as sibling to <router-outlet> and does not replace it.

See also https://angular.io/guide/component-interaction#parent-and-children-communicate-via-a-service

@Injectable() 
export class NodeService {
  private node:Subject<Node> = new BehaviorSubject<Node>([]);

  get node$(){
    return this.node.asObservable().filter(node => !!node);
  }

  addNode(data:Node) {
    this.node.next(data);
  }
}
@Component({
    selector : 'node-display',
    providers: [NodeService],
    template : `
        <router-outlet></router-outlet>
    `
})
export class NodeDisplayComponent implements OnInit {
    constructor(private nodeService:NodeService) {}
    node: Node;
    ngOnInit(): void {
        this.nodeService.getNode(path)
            .subscribe(
                node => {
                    this.nodeService.addNode(node);
                },
                err => {
                    console.log(err);
                }
            );
    }
}
export class ChildDisplay implements OnInit{
    constructor(nodeService:NodeService) {
      nodeService.node$.subscribe(n => this.node = n);
    }
}