Sharing The Data Between Components In Angular

Introduction

Angular provides component based architecture that allows modularizing the application. It means you can create multiple chunks, and convert your large component to a smaller segment that can be easily maintained. The main advantage to do this is easily understanding the component and maintenance of code. In this scenario, it is important for communication between components or share the data between the component. 

Angular provides various ways to share the data between component 

  • Using @Input decorator (Parent to Child)
  • Using @Output decorator and EventEmitter (Child to Parent)
  • Using @ViewChild decorator (Child to Parent)
  • Using a Service (Unrelated Components)

Using @Input decorator (Parent to Child)

When we define a variable with the @Input decorator in the component, it allows that variable value can get from the parent component template. The definition of the @Input decorator is defined in '@angular/core' module.

In the following example, the child component contains the variable "componentTitle" that declare with @Input decorator and this variable can be set from the parent component.

child-component.component.ts

import { Component, Input, OnInit} from '@angular/core';

@Component({
  selector: 'app-child-component',
  templateUrl: './child-component.component.html',
  styleUrls: ['./child-component.component.css']
})
export class ChildComponentComponent implements OnInit {
  @Input() componentTitle: string;
  constructor() { }
  ngOnInit() {
  }
}

child-component.component.html

<p>
	child-component:
</p>
<p>
	Data: {{componentTitle}}
</p>

parent-component.component.html

<p>
	Parent Component
</p>
<br/>
<input [(ngModel)]="title" class="form-control Report-1" type="text">
<app-child-component componentTitle="{{title}}" ></app-child-component>

parent-component.component.ts

import { Component, OnInit } from '@angular/core';
@Component({
  selector: 'app-parent-component',
  templateUrl: './parent-component.component.html',
  styleUrls: ['./parent-component.component.css']
})
export class ParentComponentComponent implements OnInit {
  title: string;
  constructor() { }
  ngOnInit() {
  }
}

Using @Output decorator and EventEmitter (Child to Parent)

To pass the data from the child component, we have to emit the data from child component and parent component will be listening for the event to get the data from Child component.

In the following example, the child component has "emitData" emitter that send the data to the parent component when user click on the "Send the Data to Parent" button. To receive the data to parent component, we have to create method to grab the data. The parent component listens for the event and when message is emitted by the child component, it captures the data in $event. 

child-component.component.ts

import { Component, Input, OnInit, Output, EventEmitter} from '@angular/core';

@Component({
  selector: 'app-child-component',
  templateUrl: './child-component.component.html',
  styleUrls: ['./child-component.component.css']
})
export class ChildComponentComponent implements OnInit {
  @Output() emitData = new EventEmitter<string> ();
  message:string = '11';
  constructor() { }
  ngOnInit() {
  }
  getMessage() {
    return this.message;
  }
  sendData() {
    this.message = "Button Click !!!";
    this.emitData.emit("Button Click!!!"); 
  }
}

child-component.component.html

<p>
    child-component:
</p>
<br/>
<button (click)="sendData()">Send the Data to Parent </button>

parent-component.component.html

<p>
	Parent Component
</p>
<br/>
<input [(ngModel)]="title" class="form-control Report-1" type="text">
<app-child-component (emitData)="emittedDataByChild($event)"></app-child-component>

parent-component.component.ts

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-parent-component',
  templateUrl: './parent-component.component.html',
  styleUrls: ['./parent-component.component.css']
})
export class ParentComponentComponent implements OnInit {
  title: string;
  childData: string;
  constructor() { }
  ngOnInit() {
  }
  emittedDataByChild(data) {
    this.childData = data;
  }
}

Using @ViewChild decorator (Child to Parent)

Another simple way to send the data is to use @ViewChild decorator. The @ViewChild decorator help to access a directive, child component and the DOM element from a component class. The @ViewChild decorator returns the element that match reference selector for defined directive, template or component. Using @ViewChild decorator, you can call a child component's method any time after the child component has got loaded. You can access the child component 's properties or method or after the "AfterViewInit" method of the parent component.

In the following example, child component instance has been created in parent component and when user click on "Get Message From Child" button, it calls "getMessage" method of child component.

parent-component.component.ts

import { Component, OnInit, ViewChild, AfterViewInit } from '@angular/core';
import { ChildComponentComponent } from '../child-component/child-component.component';

@Component({
  selector: 'app-parent-component1',
  templateUrl: './parent-component1.component.html',
  styleUrls: ['./parent-component1.component.css']
})
export class ParentComponent1Component implements OnInit, AfterViewInit {
  @ViewChild('child') private child: ChildComponentComponent;
  message: string = '';
  newName: string;
  constructor() { }
  ngOnInit() {
    this.dataservice.name.subscribe(data=>{
      this.newName = data;
    });
  }
  ngAfterViewInit() {
  }
  getChildMessage() {
    this.message = this.child.getMessage();
  }
}

parent-component.component.html

<p>
    parent-component1!
</p>
<app-child-component #child></app-child-component>

Using Services

All above described methods can be used to share the data between parent to child and vice versa. It becomes a little tricky when sharing the data between unrelated component or sibling component. 

Using BehaviorSubject, you can be able to send the data to the sibling component. It holds the data that needs to be shared with other. The component which wants to get change notification, they have to subscribe to the BehaviorSubject instance. You can publish your data change using "next" method. When next method is called, all the subscribers get notified with new data. 

In the following example, value change publishes by component1, component2 gets the change notification as it has subscribed to it.

data.Service.ts

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
@Injectable()
export class DataService {
  private nameSource = new BehaviorSubject<string>('');
  name = this.nameSource.asObservable()
  constructor() { }
  changeName(name: string) {
    this.nameSource.next(name);
  }
}

parent-component.component.ts

import { Component, OnInit } from '@angular/core';
import { DataService } from '../Services/data.Service';

@Component({
  selector: 'app-parent-component',
  templateUrl: './parent-component.component.html',
  styleUrls: ['./parent-component.component.css']
})
export class ParentComponentComponent implements OnInit {
  name: string;
  constructor(private dataservice: DataService) { }
  ngOnInit() {
  }
  changeName() {
    this.dataservice.changeName(this.name);
  }
}

parent-component1.component.ts

import { Component, OnInit } from '@angular/core';
import { ChildComponentComponent } from '../child-component/child-component.component';
import { DataService } from '../Services/data.Service';
@Component({
  selector: 'app-parent-component1',
  templateUrl: './parent-component1.component.html',
  styleUrls: ['./parent-component1.component.css']
})
export class ParentComponent1Component implements OnInit {
  newName: string;
  constructor(private dataservice: DataService) { }
  ngOnInit() {
    this.dataservice.name.subscribe(data=>{
      this.newName = data;
    });
  }
}

Summary

Angular provides multiple ways to share the data between the components. Based on your need and kind of component relation, you can select any of the methods described in this article. It is recommended to use the service method as it is independent of component relation and helps you to send data to multiple components. 

You can view or download the source code from the GitHub link here.


Similar Articles