Search code examples
angulardependency-injectionangular2-routing

Passing data into "router-outlet" child components


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.


Solution

  • <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);
        }
    }