0

In angular 2/4, I would like to get data from component A to component B and again I need to send data from B to component C and I need to display the result from Component C. Can anyone please guide me with simple example?

Srinivas
  • 35
  • 6
  • The Angular team has some great [examples](https://angular.io/guide/component-interaction). – Wrokar Nov 08 '17 at 20:39

1 Answers1

0

I can see two possible ways how to get data from component to other component.

First one, passing data through HTML when ComponentA has child ComponentB and ComponentB has child of ComponentC. Something like:

ComponentA

    @Component({
      selector: 'comp-a',
      template: `
<!--[inputDataB]="somedata" passing data to componentB -->    
<!--[validateValue]="validateData" getting data from componetB and passing data to componentB -->    
        <comp-b [inputDataB]="somedata" [validateValue]="validateData"> </comp-b>`
    })
    export class ComponentA implements OnInit {
      title = 'app works!';

      somedata: any;
      constructor(private service: MyService) {}

      ngOnInit(): void {
        this.service.getData()
          .subscribe(data => this.somedata = data);
      }

      validateData = (num: number): boolean => {
        return num >= 0;
      }
    }

ComponentB:

@Component({
      selector: 'com-b',
      template: `data of loaded in component A {{ inputDataB }}
        <button (click)="processData(4)" )> Do Something</button>
         <span *ngIf="displayCompC"> <com-c [inputDataC]="dataC"></com-c></span>       
      `
    })
    export class ComponentB implements OnInit {

      @Input()
      inputDataB: any;

      @Input()
      validateValue: (value: number) => boolean;
      dataC: number;
      displayCompC: boolean;
      constructor() {}

      ngOnInit(): void {
        this.displayCompC = false;
        // on load you can modify or process data
        this.dataC = this.inputDataB * 2;
      }

      processData = (num: number) => {
        this.displayCompC = this.validateValue(num);
      }
    }

ComonentC

@Component({
  selector: 'com-c',
  template: `data of loaded in component B {{ inputDataC }}
    {{inputDataC}}
  `
})
export class ComponentC implements OnInit {

  @Input()
  inputDataC: number;

  modifydata: number;

  constructor() {}

  ngOnInit(): void {
    // on load you can modify or process data
    this.modifydata = this.inputDataC * 5;
  }
}

Guess this is not what you want as the ComponentA has view of components B and C.

Second way is to create CommonDataMode which you inject into each component constructor. CommonDataMode would share data through other components. Something like:

    import {Component, OnInit} from '@angular/core';
    import {CommonDataModel} from './CommonDataMode';
    import {MyService} from './MyService';

    @Component({
      selector: 'app-root',
      template: `{{anyData}}`
    })
    export class AppComponent implements OnInit {

      anydata: number;
      constructor(private service: MyService, private commonDataModel: CommonDataModel) {}

      ngOnInit(): void {
        this.service.getData()
          .subscribe(data =>  {
            this.commonDataModel.data = data;
            this.anydata = data;
          });
      }
    }


@Component({
  selector: 'com-b',
  template: `data B {{ inputDataB }}
        double: {{doubleDate}}
  `
})
export class ComponentB implements OnInit {

  inputDataB: any;
  doubleDate: number;

  constructor(private commonDataModel: CommonDataModel) {}

  ngOnInit(): void {
    this.inputDataB = this.commonDataModel.data;
    this.doubleDate = this.commonDataModel.multiplyByTwo();
  }
}


@Component({
  selector: 'com-c',
  template: `data of loaded in component B {{ inputDataC }}
    {{inputDataC}}
  `
})

export class ComponentC implements OnInit {

  inputDataC: number;
  modifydata: number;

  constructor(private commonDataModel: CommonDataModel) {}

  ngOnInit(): void {
    // on load you can modify or process data
    this.modifydata = this.commonDataModel.data;
    this.modifydata = this.commonDataModel.multiplyByNumber(5);
  }
}

Now CommonDataMode

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

@Injectable()
export class CommonDataModel {

  data: number;

  multiplyByTwo = (): number => {
    return this.data * 2;
  }

  multiplyByNumber = (num: number): number => {
    return this.data * num;
  }
} 

Node that Component A needs to be loaded first. If you refresh page when you are in Component B or C then data would not be undefined.

To go around this issue provide your root module with APP_INITIALIZER and load data before app starts.

David Sajdl
  • 115
  • 1
  • 8