Passing data into “router-outlet” child components (angular 2)












61















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) my child display



export class ChildDisplay implements OnInit{

@Input()
node: Node;

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

}


It doesn't seem as thought 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.










share|improve this question



























    61















    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) my child display



    export class ChildDisplay implements OnInit{

    @Input()
    node: Node;

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

    }


    It doesn't seem as thought 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.










    share|improve this question

























      61












      61








      61


      13






      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) my child display



      export class ChildDisplay implements OnInit{

      @Input()
      node: Node;

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

      }


      It doesn't seem as thought 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.










      share|improve this question














      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) my child display



      export class ChildDisplay implements OnInit{

      @Input()
      node: Node;

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

      }


      It doesn't seem as thought 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.







      angular dependency-injection angular2-routing






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Jan 3 '17 at 19:58









      ZackZack

      3,915134586




      3,915134586
























          5 Answers
          5






          active

          oldest

          votes


















          56
















          The only way is to use a shared service.



          <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/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-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);
          }
          }





          share|improve this answer


























          • This looks like it is going to work for me. It seems a bit messy, but thems the breaks.

            – Zack
            Jan 3 '17 at 20:37











          • Yea, I pretty much just added another method "announceNewNode" to my node service, that will let the child components know when it is time to update. Then I subscribe to the service in the child component. Thanks!

            – Zack
            Jan 3 '17 at 20:38











          • In the last class, is "$." a typo? I can't find any reference to it...

            – Gyromite
            Nov 1 '17 at 21:08






          • 2





            The NodeService has a field with the name node$. That's a convention some use for naming fields that hold a reference to an observable.

            – Günter Zöchbauer
            Nov 1 '17 at 21:09













          • Can this be used to give an ID to the child? I've tried changed all the node where it's as a type to string and it doesn't seem to work or I'm doing something wrong

            – Wanjia
            Jan 24 '18 at 9:13



















          29














          Günters answer is great, I just want to point out another way without using Observables.



          Here we though have to remember that these objects are passed by reference, so if you want to do some work on the object in the child and not affect the parent object, I would suggest using Günther's solution. But if it doesn't matter, or actually is desired behavior, I would suggest the following.





          @Injectable()
          export class SharedService {

          sharedNode = {
          // properties
          };
          }


          In your parent you can assign the value:



          this.sharedService.sharedNode = this.node;


          And in your children (AND parent), inject the shared Service in your constructor. Remember to provide the service at module level providers array if you want a singleton service all over the components in that module. Alternatively, just add the service in the providers array in the parent only, then the parent and child will share the same instance of service.



          node: Node;

          ngOnInit() {
          this.node = this.sharedService.sharedNode;
          }


          And as newman kindly pointed, you can also have this.sharedService.sharedNode in the html template or a getter:



          get sharedNode(){
          return this.sharedService.sharedNode;
          }





          share|improve this answer





















          • 2





            Wish I could give out more than once accept.

            – Zack
            Jan 3 '17 at 20:39






          • 2





            done...........

            – Zack
            Jan 3 '17 at 20:42






          • 4





            you can/should bind to sharedService.sharedNode in html directly. This way, updates in sharedNode will be kept in sync.

            – newman
            Apr 6 '17 at 4:09



















          5














          Service:



          import {Injectable, EventEmitter} from "@angular/core";    

          @Injectable()
          export class DataService {
          onGetData: EventEmitter = new EventEmitter();

          getData() {
          this.http.post(...params).map(res => {
          this.onGetData.emit(res.json());
          })
          }


          Component:



          import {Component} from '@angular/core';    
          import {DataService} from "../services/data.service";

          @Component()
          export class MyComponent {
          constructor(private DataService:DataService) {
          this.DataService.onGetData.subscribe(res => {
          (from service on .emit() )
          })
          }

          //To send data to all subscribers from current component
          sendData() {
          this.DataService.onGetData.emit(--NEW DATA--);
          }
          }





          share|improve this answer


























          • Please include code as text, not as an image

            – Rob
            Aug 7 '17 at 7:25











          • This should be the best answer! Very neat and clean reuse. You saved my day buddy. Emitting the data and subsricbing to it is a great idea.

            – JavaFreak
            Aug 29 '17 at 10:03








          • 2





            @JavaFreak and egor: This approach is not recommended, check: stackoverflow.com/a/36076701/6294072 if you want to go this way, use a Subject or BehaviorSubject instead, like Günter presented.

            – AJT_82
            Oct 6 '17 at 12:23













          • Agree. Good solution from stackoverflow.com/a/36076701/6294072

            – egor.xyz
            Oct 15 '17 at 9:47






          • 3





            And what to do if child component under router-outlet?

            – V. Kalyuzhnyu
            Dec 19 '17 at 11:04



















          1














          There are 3 ways to pass data from Parent to Children




          1. Through shareable service : you should store into a service the data you would like to share with the children


          2. Through Children Router Resolver if you have to receive different data



            this.data = this.route.snaphsot.data['dataFromResolver'];



          3. Through Parent Router Resolver if your have to receive the same data from parent



            this.data = this.route.parent.snaphsot.data['dataFromResolver'];



          Note1: You can read about resolver here. There is also an example of resolver and how to register the resolver into the module and then retrieve data from resolver into the component. The resolver registration is the same on the parent and child.



          Note2: You can read about ActivatedRoute here to be able to get data from router






          share|improve this answer































            0














            Following this question, in Angular 7.2 you can pass data from parent to child using the history state. So you can do something like




            Send:



            this.router.navigate(['action-selection'], { state: { example: 'bar' } });


            Retrieve:



            constructor(private router: Router) {
            console.log(this.router.getCurrentNavigation().extras.state.example);
            }



            But be careful to be consistent. For example, suppose you want to display a list on a left side bar and the details of the selected item on the right by using a router-outlet. Something like:





            Item 1 (x) | ..............................................



            Item 2 (x) | ......Selected Item Details.......



            Item 3 (x) | ..............................................



            Item 4 (x) | ..............................................





            Now, suppose you have already clicked some items. Clicking the browsers back buttons will show the details from the previous item. But what if, meanwhile, you have clicked the (x) and delete from your list that item? Then performing the back click, will show you the details of a deleted item.






            share|improve this answer























              Your Answer






              StackExchange.ifUsing("editor", function () {
              StackExchange.using("externalEditor", function () {
              StackExchange.using("snippets", function () {
              StackExchange.snippets.init();
              });
              });
              }, "code-snippets");

              StackExchange.ready(function() {
              var channelOptions = {
              tags: "".split(" "),
              id: "1"
              };
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function() {
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled) {
              StackExchange.using("snippets", function() {
              createEditor();
              });
              }
              else {
              createEditor();
              }
              });

              function createEditor() {
              StackExchange.prepareEditor({
              heartbeatType: 'answer',
              autoActivateHeartbeat: false,
              convertImagesToLinks: true,
              noModals: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: 10,
              bindNavPrevention: true,
              postfix: "",
              imageUploader: {
              brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
              allowUrls: true
              },
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              });


              }
              });














              draft saved

              draft discarded


















              StackExchange.ready(
              function () {
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f41451375%2fpassing-data-into-router-outlet-child-components-angular-2%23new-answer', 'question_page');
              }
              );

              Post as a guest















              Required, but never shown

























              5 Answers
              5






              active

              oldest

              votes








              5 Answers
              5






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes









              56
















              The only way is to use a shared service.



              <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/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-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);
              }
              }





              share|improve this answer


























              • This looks like it is going to work for me. It seems a bit messy, but thems the breaks.

                – Zack
                Jan 3 '17 at 20:37











              • Yea, I pretty much just added another method "announceNewNode" to my node service, that will let the child components know when it is time to update. Then I subscribe to the service in the child component. Thanks!

                – Zack
                Jan 3 '17 at 20:38











              • In the last class, is "$." a typo? I can't find any reference to it...

                – Gyromite
                Nov 1 '17 at 21:08






              • 2





                The NodeService has a field with the name node$. That's a convention some use for naming fields that hold a reference to an observable.

                – Günter Zöchbauer
                Nov 1 '17 at 21:09













              • Can this be used to give an ID to the child? I've tried changed all the node where it's as a type to string and it doesn't seem to work or I'm doing something wrong

                – Wanjia
                Jan 24 '18 at 9:13
















              56
















              The only way is to use a shared service.



              <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/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-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);
              }
              }





              share|improve this answer


























              • This looks like it is going to work for me. It seems a bit messy, but thems the breaks.

                – Zack
                Jan 3 '17 at 20:37











              • Yea, I pretty much just added another method "announceNewNode" to my node service, that will let the child components know when it is time to update. Then I subscribe to the service in the child component. Thanks!

                – Zack
                Jan 3 '17 at 20:38











              • In the last class, is "$." a typo? I can't find any reference to it...

                – Gyromite
                Nov 1 '17 at 21:08






              • 2





                The NodeService has a field with the name node$. That's a convention some use for naming fields that hold a reference to an observable.

                – Günter Zöchbauer
                Nov 1 '17 at 21:09













              • Can this be used to give an ID to the child? I've tried changed all the node where it's as a type to string and it doesn't seem to work or I'm doing something wrong

                – Wanjia
                Jan 24 '18 at 9:13














              56












              56








              56









              The only way is to use a shared service.



              <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/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-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);
              }
              }





              share|improve this answer

















              The only way is to use a shared service.



              <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/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-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);
              }
              }






              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited Aug 18 '18 at 10:50









              Gabrielus

              122111




              122111










              answered Jan 3 '17 at 20:04









              Günter ZöchbauerGünter Zöchbauer

              332k701005938




              332k701005938













              • This looks like it is going to work for me. It seems a bit messy, but thems the breaks.

                – Zack
                Jan 3 '17 at 20:37











              • Yea, I pretty much just added another method "announceNewNode" to my node service, that will let the child components know when it is time to update. Then I subscribe to the service in the child component. Thanks!

                – Zack
                Jan 3 '17 at 20:38











              • In the last class, is "$." a typo? I can't find any reference to it...

                – Gyromite
                Nov 1 '17 at 21:08






              • 2





                The NodeService has a field with the name node$. That's a convention some use for naming fields that hold a reference to an observable.

                – Günter Zöchbauer
                Nov 1 '17 at 21:09













              • Can this be used to give an ID to the child? I've tried changed all the node where it's as a type to string and it doesn't seem to work or I'm doing something wrong

                – Wanjia
                Jan 24 '18 at 9:13



















              • This looks like it is going to work for me. It seems a bit messy, but thems the breaks.

                – Zack
                Jan 3 '17 at 20:37











              • Yea, I pretty much just added another method "announceNewNode" to my node service, that will let the child components know when it is time to update. Then I subscribe to the service in the child component. Thanks!

                – Zack
                Jan 3 '17 at 20:38











              • In the last class, is "$." a typo? I can't find any reference to it...

                – Gyromite
                Nov 1 '17 at 21:08






              • 2





                The NodeService has a field with the name node$. That's a convention some use for naming fields that hold a reference to an observable.

                – Günter Zöchbauer
                Nov 1 '17 at 21:09













              • Can this be used to give an ID to the child? I've tried changed all the node where it's as a type to string and it doesn't seem to work or I'm doing something wrong

                – Wanjia
                Jan 24 '18 at 9:13

















              This looks like it is going to work for me. It seems a bit messy, but thems the breaks.

              – Zack
              Jan 3 '17 at 20:37





              This looks like it is going to work for me. It seems a bit messy, but thems the breaks.

              – Zack
              Jan 3 '17 at 20:37













              Yea, I pretty much just added another method "announceNewNode" to my node service, that will let the child components know when it is time to update. Then I subscribe to the service in the child component. Thanks!

              – Zack
              Jan 3 '17 at 20:38





              Yea, I pretty much just added another method "announceNewNode" to my node service, that will let the child components know when it is time to update. Then I subscribe to the service in the child component. Thanks!

              – Zack
              Jan 3 '17 at 20:38













              In the last class, is "$." a typo? I can't find any reference to it...

              – Gyromite
              Nov 1 '17 at 21:08





              In the last class, is "$." a typo? I can't find any reference to it...

              – Gyromite
              Nov 1 '17 at 21:08




              2




              2





              The NodeService has a field with the name node$. That's a convention some use for naming fields that hold a reference to an observable.

              – Günter Zöchbauer
              Nov 1 '17 at 21:09







              The NodeService has a field with the name node$. That's a convention some use for naming fields that hold a reference to an observable.

              – Günter Zöchbauer
              Nov 1 '17 at 21:09















              Can this be used to give an ID to the child? I've tried changed all the node where it's as a type to string and it doesn't seem to work or I'm doing something wrong

              – Wanjia
              Jan 24 '18 at 9:13





              Can this be used to give an ID to the child? I've tried changed all the node where it's as a type to string and it doesn't seem to work or I'm doing something wrong

              – Wanjia
              Jan 24 '18 at 9:13













              29














              Günters answer is great, I just want to point out another way without using Observables.



              Here we though have to remember that these objects are passed by reference, so if you want to do some work on the object in the child and not affect the parent object, I would suggest using Günther's solution. But if it doesn't matter, or actually is desired behavior, I would suggest the following.





              @Injectable()
              export class SharedService {

              sharedNode = {
              // properties
              };
              }


              In your parent you can assign the value:



              this.sharedService.sharedNode = this.node;


              And in your children (AND parent), inject the shared Service in your constructor. Remember to provide the service at module level providers array if you want a singleton service all over the components in that module. Alternatively, just add the service in the providers array in the parent only, then the parent and child will share the same instance of service.



              node: Node;

              ngOnInit() {
              this.node = this.sharedService.sharedNode;
              }


              And as newman kindly pointed, you can also have this.sharedService.sharedNode in the html template or a getter:



              get sharedNode(){
              return this.sharedService.sharedNode;
              }





              share|improve this answer





















              • 2





                Wish I could give out more than once accept.

                – Zack
                Jan 3 '17 at 20:39






              • 2





                done...........

                – Zack
                Jan 3 '17 at 20:42






              • 4





                you can/should bind to sharedService.sharedNode in html directly. This way, updates in sharedNode will be kept in sync.

                – newman
                Apr 6 '17 at 4:09
















              29














              Günters answer is great, I just want to point out another way without using Observables.



              Here we though have to remember that these objects are passed by reference, so if you want to do some work on the object in the child and not affect the parent object, I would suggest using Günther's solution. But if it doesn't matter, or actually is desired behavior, I would suggest the following.





              @Injectable()
              export class SharedService {

              sharedNode = {
              // properties
              };
              }


              In your parent you can assign the value:



              this.sharedService.sharedNode = this.node;


              And in your children (AND parent), inject the shared Service in your constructor. Remember to provide the service at module level providers array if you want a singleton service all over the components in that module. Alternatively, just add the service in the providers array in the parent only, then the parent and child will share the same instance of service.



              node: Node;

              ngOnInit() {
              this.node = this.sharedService.sharedNode;
              }


              And as newman kindly pointed, you can also have this.sharedService.sharedNode in the html template or a getter:



              get sharedNode(){
              return this.sharedService.sharedNode;
              }





              share|improve this answer





















              • 2





                Wish I could give out more than once accept.

                – Zack
                Jan 3 '17 at 20:39






              • 2





                done...........

                – Zack
                Jan 3 '17 at 20:42






              • 4





                you can/should bind to sharedService.sharedNode in html directly. This way, updates in sharedNode will be kept in sync.

                – newman
                Apr 6 '17 at 4:09














              29












              29








              29







              Günters answer is great, I just want to point out another way without using Observables.



              Here we though have to remember that these objects are passed by reference, so if you want to do some work on the object in the child and not affect the parent object, I would suggest using Günther's solution. But if it doesn't matter, or actually is desired behavior, I would suggest the following.





              @Injectable()
              export class SharedService {

              sharedNode = {
              // properties
              };
              }


              In your parent you can assign the value:



              this.sharedService.sharedNode = this.node;


              And in your children (AND parent), inject the shared Service in your constructor. Remember to provide the service at module level providers array if you want a singleton service all over the components in that module. Alternatively, just add the service in the providers array in the parent only, then the parent and child will share the same instance of service.



              node: Node;

              ngOnInit() {
              this.node = this.sharedService.sharedNode;
              }


              And as newman kindly pointed, you can also have this.sharedService.sharedNode in the html template or a getter:



              get sharedNode(){
              return this.sharedService.sharedNode;
              }





              share|improve this answer















              Günters answer is great, I just want to point out another way without using Observables.



              Here we though have to remember that these objects are passed by reference, so if you want to do some work on the object in the child and not affect the parent object, I would suggest using Günther's solution. But if it doesn't matter, or actually is desired behavior, I would suggest the following.





              @Injectable()
              export class SharedService {

              sharedNode = {
              // properties
              };
              }


              In your parent you can assign the value:



              this.sharedService.sharedNode = this.node;


              And in your children (AND parent), inject the shared Service in your constructor. Remember to provide the service at module level providers array if you want a singleton service all over the components in that module. Alternatively, just add the service in the providers array in the parent only, then the parent and child will share the same instance of service.



              node: Node;

              ngOnInit() {
              this.node = this.sharedService.sharedNode;
              }


              And as newman kindly pointed, you can also have this.sharedService.sharedNode in the html template or a getter:



              get sharedNode(){
              return this.sharedService.sharedNode;
              }






              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited Aug 19 '17 at 15:38

























              answered Jan 3 '17 at 20:07









              AJT_82AJT_82

              37k1369100




              37k1369100








              • 2





                Wish I could give out more than once accept.

                – Zack
                Jan 3 '17 at 20:39






              • 2





                done...........

                – Zack
                Jan 3 '17 at 20:42






              • 4





                you can/should bind to sharedService.sharedNode in html directly. This way, updates in sharedNode will be kept in sync.

                – newman
                Apr 6 '17 at 4:09














              • 2





                Wish I could give out more than once accept.

                – Zack
                Jan 3 '17 at 20:39






              • 2





                done...........

                – Zack
                Jan 3 '17 at 20:42






              • 4





                you can/should bind to sharedService.sharedNode in html directly. This way, updates in sharedNode will be kept in sync.

                – newman
                Apr 6 '17 at 4:09








              2




              2





              Wish I could give out more than once accept.

              – Zack
              Jan 3 '17 at 20:39





              Wish I could give out more than once accept.

              – Zack
              Jan 3 '17 at 20:39




              2




              2





              done...........

              – Zack
              Jan 3 '17 at 20:42





              done...........

              – Zack
              Jan 3 '17 at 20:42




              4




              4





              you can/should bind to sharedService.sharedNode in html directly. This way, updates in sharedNode will be kept in sync.

              – newman
              Apr 6 '17 at 4:09





              you can/should bind to sharedService.sharedNode in html directly. This way, updates in sharedNode will be kept in sync.

              – newman
              Apr 6 '17 at 4:09











              5














              Service:



              import {Injectable, EventEmitter} from "@angular/core";    

              @Injectable()
              export class DataService {
              onGetData: EventEmitter = new EventEmitter();

              getData() {
              this.http.post(...params).map(res => {
              this.onGetData.emit(res.json());
              })
              }


              Component:



              import {Component} from '@angular/core';    
              import {DataService} from "../services/data.service";

              @Component()
              export class MyComponent {
              constructor(private DataService:DataService) {
              this.DataService.onGetData.subscribe(res => {
              (from service on .emit() )
              })
              }

              //To send data to all subscribers from current component
              sendData() {
              this.DataService.onGetData.emit(--NEW DATA--);
              }
              }





              share|improve this answer


























              • Please include code as text, not as an image

                – Rob
                Aug 7 '17 at 7:25











              • This should be the best answer! Very neat and clean reuse. You saved my day buddy. Emitting the data and subsricbing to it is a great idea.

                – JavaFreak
                Aug 29 '17 at 10:03








              • 2





                @JavaFreak and egor: This approach is not recommended, check: stackoverflow.com/a/36076701/6294072 if you want to go this way, use a Subject or BehaviorSubject instead, like Günter presented.

                – AJT_82
                Oct 6 '17 at 12:23













              • Agree. Good solution from stackoverflow.com/a/36076701/6294072

                – egor.xyz
                Oct 15 '17 at 9:47






              • 3





                And what to do if child component under router-outlet?

                – V. Kalyuzhnyu
                Dec 19 '17 at 11:04
















              5














              Service:



              import {Injectable, EventEmitter} from "@angular/core";    

              @Injectable()
              export class DataService {
              onGetData: EventEmitter = new EventEmitter();

              getData() {
              this.http.post(...params).map(res => {
              this.onGetData.emit(res.json());
              })
              }


              Component:



              import {Component} from '@angular/core';    
              import {DataService} from "../services/data.service";

              @Component()
              export class MyComponent {
              constructor(private DataService:DataService) {
              this.DataService.onGetData.subscribe(res => {
              (from service on .emit() )
              })
              }

              //To send data to all subscribers from current component
              sendData() {
              this.DataService.onGetData.emit(--NEW DATA--);
              }
              }





              share|improve this answer


























              • Please include code as text, not as an image

                – Rob
                Aug 7 '17 at 7:25











              • This should be the best answer! Very neat and clean reuse. You saved my day buddy. Emitting the data and subsricbing to it is a great idea.

                – JavaFreak
                Aug 29 '17 at 10:03








              • 2





                @JavaFreak and egor: This approach is not recommended, check: stackoverflow.com/a/36076701/6294072 if you want to go this way, use a Subject or BehaviorSubject instead, like Günter presented.

                – AJT_82
                Oct 6 '17 at 12:23













              • Agree. Good solution from stackoverflow.com/a/36076701/6294072

                – egor.xyz
                Oct 15 '17 at 9:47






              • 3





                And what to do if child component under router-outlet?

                – V. Kalyuzhnyu
                Dec 19 '17 at 11:04














              5












              5








              5







              Service:



              import {Injectable, EventEmitter} from "@angular/core";    

              @Injectable()
              export class DataService {
              onGetData: EventEmitter = new EventEmitter();

              getData() {
              this.http.post(...params).map(res => {
              this.onGetData.emit(res.json());
              })
              }


              Component:



              import {Component} from '@angular/core';    
              import {DataService} from "../services/data.service";

              @Component()
              export class MyComponent {
              constructor(private DataService:DataService) {
              this.DataService.onGetData.subscribe(res => {
              (from service on .emit() )
              })
              }

              //To send data to all subscribers from current component
              sendData() {
              this.DataService.onGetData.emit(--NEW DATA--);
              }
              }





              share|improve this answer















              Service:



              import {Injectable, EventEmitter} from "@angular/core";    

              @Injectable()
              export class DataService {
              onGetData: EventEmitter = new EventEmitter();

              getData() {
              this.http.post(...params).map(res => {
              this.onGetData.emit(res.json());
              })
              }


              Component:



              import {Component} from '@angular/core';    
              import {DataService} from "../services/data.service";

              @Component()
              export class MyComponent {
              constructor(private DataService:DataService) {
              this.DataService.onGetData.subscribe(res => {
              (from service on .emit() )
              })
              }

              //To send data to all subscribers from current component
              sendData() {
              this.DataService.onGetData.emit(--NEW DATA--);
              }
              }






              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited Aug 7 '17 at 9:46

























              answered Aug 7 '17 at 7:24









              egor.xyzegor.xyz

              1,1681111




              1,1681111













              • Please include code as text, not as an image

                – Rob
                Aug 7 '17 at 7:25











              • This should be the best answer! Very neat and clean reuse. You saved my day buddy. Emitting the data and subsricbing to it is a great idea.

                – JavaFreak
                Aug 29 '17 at 10:03








              • 2





                @JavaFreak and egor: This approach is not recommended, check: stackoverflow.com/a/36076701/6294072 if you want to go this way, use a Subject or BehaviorSubject instead, like Günter presented.

                – AJT_82
                Oct 6 '17 at 12:23













              • Agree. Good solution from stackoverflow.com/a/36076701/6294072

                – egor.xyz
                Oct 15 '17 at 9:47






              • 3





                And what to do if child component under router-outlet?

                – V. Kalyuzhnyu
                Dec 19 '17 at 11:04



















              • Please include code as text, not as an image

                – Rob
                Aug 7 '17 at 7:25











              • This should be the best answer! Very neat and clean reuse. You saved my day buddy. Emitting the data and subsricbing to it is a great idea.

                – JavaFreak
                Aug 29 '17 at 10:03








              • 2





                @JavaFreak and egor: This approach is not recommended, check: stackoverflow.com/a/36076701/6294072 if you want to go this way, use a Subject or BehaviorSubject instead, like Günter presented.

                – AJT_82
                Oct 6 '17 at 12:23













              • Agree. Good solution from stackoverflow.com/a/36076701/6294072

                – egor.xyz
                Oct 15 '17 at 9:47






              • 3





                And what to do if child component under router-outlet?

                – V. Kalyuzhnyu
                Dec 19 '17 at 11:04

















              Please include code as text, not as an image

              – Rob
              Aug 7 '17 at 7:25





              Please include code as text, not as an image

              – Rob
              Aug 7 '17 at 7:25













              This should be the best answer! Very neat and clean reuse. You saved my day buddy. Emitting the data and subsricbing to it is a great idea.

              – JavaFreak
              Aug 29 '17 at 10:03







              This should be the best answer! Very neat and clean reuse. You saved my day buddy. Emitting the data and subsricbing to it is a great idea.

              – JavaFreak
              Aug 29 '17 at 10:03






              2




              2





              @JavaFreak and egor: This approach is not recommended, check: stackoverflow.com/a/36076701/6294072 if you want to go this way, use a Subject or BehaviorSubject instead, like Günter presented.

              – AJT_82
              Oct 6 '17 at 12:23







              @JavaFreak and egor: This approach is not recommended, check: stackoverflow.com/a/36076701/6294072 if you want to go this way, use a Subject or BehaviorSubject instead, like Günter presented.

              – AJT_82
              Oct 6 '17 at 12:23















              Agree. Good solution from stackoverflow.com/a/36076701/6294072

              – egor.xyz
              Oct 15 '17 at 9:47





              Agree. Good solution from stackoverflow.com/a/36076701/6294072

              – egor.xyz
              Oct 15 '17 at 9:47




              3




              3





              And what to do if child component under router-outlet?

              – V. Kalyuzhnyu
              Dec 19 '17 at 11:04





              And what to do if child component under router-outlet?

              – V. Kalyuzhnyu
              Dec 19 '17 at 11:04











              1














              There are 3 ways to pass data from Parent to Children




              1. Through shareable service : you should store into a service the data you would like to share with the children


              2. Through Children Router Resolver if you have to receive different data



                this.data = this.route.snaphsot.data['dataFromResolver'];



              3. Through Parent Router Resolver if your have to receive the same data from parent



                this.data = this.route.parent.snaphsot.data['dataFromResolver'];



              Note1: You can read about resolver here. There is also an example of resolver and how to register the resolver into the module and then retrieve data from resolver into the component. The resolver registration is the same on the parent and child.



              Note2: You can read about ActivatedRoute here to be able to get data from router






              share|improve this answer




























                1














                There are 3 ways to pass data from Parent to Children




                1. Through shareable service : you should store into a service the data you would like to share with the children


                2. Through Children Router Resolver if you have to receive different data



                  this.data = this.route.snaphsot.data['dataFromResolver'];



                3. Through Parent Router Resolver if your have to receive the same data from parent



                  this.data = this.route.parent.snaphsot.data['dataFromResolver'];



                Note1: You can read about resolver here. There is also an example of resolver and how to register the resolver into the module and then retrieve data from resolver into the component. The resolver registration is the same on the parent and child.



                Note2: You can read about ActivatedRoute here to be able to get data from router






                share|improve this answer


























                  1












                  1








                  1







                  There are 3 ways to pass data from Parent to Children




                  1. Through shareable service : you should store into a service the data you would like to share with the children


                  2. Through Children Router Resolver if you have to receive different data



                    this.data = this.route.snaphsot.data['dataFromResolver'];



                  3. Through Parent Router Resolver if your have to receive the same data from parent



                    this.data = this.route.parent.snaphsot.data['dataFromResolver'];



                  Note1: You can read about resolver here. There is also an example of resolver and how to register the resolver into the module and then retrieve data from resolver into the component. The resolver registration is the same on the parent and child.



                  Note2: You can read about ActivatedRoute here to be able to get data from router






                  share|improve this answer













                  There are 3 ways to pass data from Parent to Children




                  1. Through shareable service : you should store into a service the data you would like to share with the children


                  2. Through Children Router Resolver if you have to receive different data



                    this.data = this.route.snaphsot.data['dataFromResolver'];



                  3. Through Parent Router Resolver if your have to receive the same data from parent



                    this.data = this.route.parent.snaphsot.data['dataFromResolver'];



                  Note1: You can read about resolver here. There is also an example of resolver and how to register the resolver into the module and then retrieve data from resolver into the component. The resolver registration is the same on the parent and child.



                  Note2: You can read about ActivatedRoute here to be able to get data from router







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Nov 22 '18 at 8:41









                  Rzv RazvanRzv Razvan

                  555311




                  555311























                      0














                      Following this question, in Angular 7.2 you can pass data from parent to child using the history state. So you can do something like




                      Send:



                      this.router.navigate(['action-selection'], { state: { example: 'bar' } });


                      Retrieve:



                      constructor(private router: Router) {
                      console.log(this.router.getCurrentNavigation().extras.state.example);
                      }



                      But be careful to be consistent. For example, suppose you want to display a list on a left side bar and the details of the selected item on the right by using a router-outlet. Something like:





                      Item 1 (x) | ..............................................



                      Item 2 (x) | ......Selected Item Details.......



                      Item 3 (x) | ..............................................



                      Item 4 (x) | ..............................................





                      Now, suppose you have already clicked some items. Clicking the browsers back buttons will show the details from the previous item. But what if, meanwhile, you have clicked the (x) and delete from your list that item? Then performing the back click, will show you the details of a deleted item.






                      share|improve this answer




























                        0














                        Following this question, in Angular 7.2 you can pass data from parent to child using the history state. So you can do something like




                        Send:



                        this.router.navigate(['action-selection'], { state: { example: 'bar' } });


                        Retrieve:



                        constructor(private router: Router) {
                        console.log(this.router.getCurrentNavigation().extras.state.example);
                        }



                        But be careful to be consistent. For example, suppose you want to display a list on a left side bar and the details of the selected item on the right by using a router-outlet. Something like:





                        Item 1 (x) | ..............................................



                        Item 2 (x) | ......Selected Item Details.......



                        Item 3 (x) | ..............................................



                        Item 4 (x) | ..............................................





                        Now, suppose you have already clicked some items. Clicking the browsers back buttons will show the details from the previous item. But what if, meanwhile, you have clicked the (x) and delete from your list that item? Then performing the back click, will show you the details of a deleted item.






                        share|improve this answer


























                          0












                          0








                          0







                          Following this question, in Angular 7.2 you can pass data from parent to child using the history state. So you can do something like




                          Send:



                          this.router.navigate(['action-selection'], { state: { example: 'bar' } });


                          Retrieve:



                          constructor(private router: Router) {
                          console.log(this.router.getCurrentNavigation().extras.state.example);
                          }



                          But be careful to be consistent. For example, suppose you want to display a list on a left side bar and the details of the selected item on the right by using a router-outlet. Something like:





                          Item 1 (x) | ..............................................



                          Item 2 (x) | ......Selected Item Details.......



                          Item 3 (x) | ..............................................



                          Item 4 (x) | ..............................................





                          Now, suppose you have already clicked some items. Clicking the browsers back buttons will show the details from the previous item. But what if, meanwhile, you have clicked the (x) and delete from your list that item? Then performing the back click, will show you the details of a deleted item.






                          share|improve this answer













                          Following this question, in Angular 7.2 you can pass data from parent to child using the history state. So you can do something like




                          Send:



                          this.router.navigate(['action-selection'], { state: { example: 'bar' } });


                          Retrieve:



                          constructor(private router: Router) {
                          console.log(this.router.getCurrentNavigation().extras.state.example);
                          }



                          But be careful to be consistent. For example, suppose you want to display a list on a left side bar and the details of the selected item on the right by using a router-outlet. Something like:





                          Item 1 (x) | ..............................................



                          Item 2 (x) | ......Selected Item Details.......



                          Item 3 (x) | ..............................................



                          Item 4 (x) | ..............................................





                          Now, suppose you have already clicked some items. Clicking the browsers back buttons will show the details from the previous item. But what if, meanwhile, you have clicked the (x) and delete from your list that item? Then performing the back click, will show you the details of a deleted item.







                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered Mar 13 at 9:06









                          MTZMTZ

                          8614




                          8614






























                              draft saved

                              draft discarded




















































                              Thanks for contributing an answer to Stack Overflow!


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid



                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.


                              To learn more, see our tips on writing great answers.




                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function () {
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f41451375%2fpassing-data-into-router-outlet-child-components-angular-2%23new-answer', 'question_page');
                              }
                              );

                              Post as a guest















                              Required, but never shown





















































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown

































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown







                              這個網誌中的熱門文章

                              Xamarin.form Move up view when keyboard appear

                              Post-Redirect-Get with Spring WebFlux and Thymeleaf

                              Anylogic : not able to use stopDelay()