LinkIT
Published in

LinkIT

Angular Component Interaction

What is Component Interaction And How do Components Interact With Other Components In Angular?

We all know that in Angular everything are component. It is important to interact with other components because of data sharing between them. before moving into component interaction, we need to understand how components are arranged in the Angular application. Mainly there are 2 types of component structures.

  1. Related components (Parent, Child interaction)
  2. Non-related components or Sibling structured components.
Component Structure in Angular

What Is Component Interaction And It’s Types

One component of the angular application is sharing data with another component called “Component Interaction”. In Angular, there are three types of component interactions.

  1. Passing Data from Parent to Child
  2. Passing Data from Child to Parent
  3. Data sharing between Non-related components (between siblings).

Passing Data from Parent to Child

When we use one component within another component then, the base component is called as Parent component and the used component is called as Child component. For passing data from the parent component to the child component, we use the “Input” decorator. Through this interaction, we can share data from the parent component to the child component and when we change the behavior of the data at the Parent component then it will reflect in the Child component also. The below example shows, How Parent to child interaction occurs.

Parent Component: app.ts →

import { Component } from '@angular/core';@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'component-interaction from Parent';
age = 25;
increase(){
this.age = this.age + 1;
}
}

app.html →

<div style="background-color: yellow; padding: 10px;">
<h1>Parent Component!</h1><br>
<h2>{{title}}</h2>
<h2>Age From Parent: {{age}}</h2><br>
<button (click)="increase()">Increase</button><br><br>
<app-history
[childTitle]="title"
[childAge]="age">
</app-history>
</div><router-outlet></router-outlet>

Child component: history.ts →

import { Component, Input } from '@angular/core';@Component({
selector: 'app-history',
templateUrl: './history.component.html',
styleUrls: ['./history.component.css']
})
export class HistoryComponent{
@Input() childTitle='';
@Input() childAge=0;
}

history.html→

<div style="background-color: aqua; padding: 10px; margin: 5px;">
<h1>Cild Component!</h1>
<h2>Title From Parent Component: {{childTitle}}</h2><br>
<h2>Age: {{childAge}}</h2>
</div>
Parent to Child interaction

The above image shows how the interaction works. and from the parent component when we click the increase button, the Age of the Parent will be increased and the Age of the child also will be increased. By using Parent to child interaction, we can pass data from parents to the child and that shared data behaves as same as the parent component.

Passing Data from Child to Parent

In this type of interaction, when a dispatch occurs in the child component then the data is emitted from the child which can be listened to by the parent component. For Child to Parent interaction, we use the ‘Output’ decorator and ‘EventEmitter’ dispatch. This type of interaction is ideal when, we want to share data changes that occur on things like button clicks, form entries and other user events.

For this type of interaction,

  1. In the parent component, we need to create a function to retrieve data and set it equal to the count variable.
  2. In the child component, declare the counter event variable with the Output decorator and set it equal to the new EventEmitter object, and declare the count variable with ‘0’ as an initial value.
  3. Create a function named increase that increases the value of count by one and calls emit on the counter event with the count value which we want to pass to the parent component.
  4. Create a button in the child component to trigger the above function.
  5. Then parent subscribes to this counter event outputted by the child component and then, runs the increase function of the parent class whenever this event from the child component is triggered.

The below example shows how Child to Parent interaction happens.

Parent Component: app.ts →

import { Component } from '@angular/core';@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
count=0;
increase(event:number){
this.count=event;
}
}

app.html →

<div style="background-color: yellow; padding: 10px; margin: 30px; margin-left: 50px; margin-right: 50px; margin-top: 50px;">
<h1>Parent Component</h1>
<h2>Count: {{count}}</h2>
<app-history
(counter)="increase($event)">
</app-history>
</div>

Child component: history.ts →

import { Component, EventEmitter,OnInit, Output } from '@angular/core';@Component({
selector: 'app-history',
templateUrl: './history.component.html',
styleUrls: ['./history.component.css']
})
export class HistoryComponent implements OnInit {
count=0;
@Output()
counter=new EventEmitter<number>();
constructor() { }
ngOnInit(): void {}
increaseChild(){
this.count=this.count+1;
this.counter.emit(this.count);
}
}

history.html →

<div style="background-color: aqua; padding: 10px; margin: 5px;">
<h1>Child Component</h1>
<h2>Count: {{count}}</h2>
<button (click)="increaseChild()">Increase</button>
</div>
Child-to-Parent Interaction

When the user clicks the Increase button Count of the child component increases by one and that value is listened to by the parent component and displayed in the parent component.

Data Sharing Between Non-related Components

When sharing data between components that are not connected directly, we can use this method. Here we use shared service to set and get values from non-related components. And we use BehaviorSubject for this type of interaction. By using this interaction, the data is always will be in sync.

Steps for data sharing between non-related components:-

  1. Create a service class called “DataService” and create a private BehaviorSubject that will hold the current value of the count.
  2. Define the currentCount variable in the service class to handle this data stream as an Observable and that will be used by other components.
  3. Create a function in the service class that calls the next method on the BehaviorSubject to change its value.
  4. Inject the DataService class in the constructor of the component which uses the current count value, then subscribe to the currentCount observable and set its value equal to the count variable.
  5. And also we create a function at any component (parent/child/sibling component) to change the value of the count variable. Once this function is executed then, the new data for the count is automatically broadcast to all other components.

The below example shows the Data sharing between sibling components,

data.service.ts →

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
@Injectable()
export class DataService {
private countSource = new BehaviorSubject(0);
currentCount = this.countSource.asObservable();
constructor() { }
changeCount(count: number) {
this.countSource.next(count);
}
}

Parent Component: app.ts →

import { Component } from '@angular/core';
import { DataService } from './data.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
count=0;
constructor(private data: DataService) { }
ngOnInit() {
this.data.currentCount.subscribe(count => this.count = count);
}
}

app.html →

<a style="margin: 50px; " routerLink="/customers">Customers</a>
<div style="background-color: yellow; padding: 10px; margin: 30px; margin-left: 50px; margin-right: 50px; margin-top: 50px;">
<h1>Parent Component</h1>
<h2>Count: {{count}}</h2>
<app-history></app-history>
</div>
<router-outlet></router-outlet>

Child component: history.ts →

import { Component, OnInit } from '@angular/core';
import { DataService } from '../data.service';
@Component({
selector: 'app-history',
templateUrl: './history.component.html',
styleUrls: ['./history.component.css']
})
export class HistoryComponent implements OnInit {
count=0;
constructor(private data: DataService) { }
ngOnInit() {
this.data.currentCount.subscribe(count => this.count = count);
}
}

history.html→

<div style="background-color: aqua; padding: 10px; margin: 5px;">
<h1>Child Component</h1>
<h2>Count: {{count}}</h2>
</div>

Sibling Component: customer.ts→

import { Component, OnInit } from '@angular/core';
import { DataService } from '../data.service';
@Component({
selector: 'app-customer',
templateUrl: './customer.component.html',
styleUrls: ['./customer.component.css']
})
export class CustomerComponent implements OnInit {
count=0;
constructor(private data: DataService) { }
ngOnInit() {
this.data.currentCount.subscribe(count => this.count = count);
}
increaseCount() {
this.count=this.count+1;
this.data.changeCount(this.count);
}
}

customer.html →

<div style="background-color: blueviolet; padding: 20px; margin: 30px; margin-left: 50px; margin-right: 50px; margin-top: 30px;">  <h1>Sibling Component</h1>
<h2>Count: {{count}}</h2>
<button (click)="increaseCount()">Increase</button>
</div>

The below picture shows the output of the Component interaction between non-related components using a common service class.

Data sharing between components by Common service

In the above example, the App component (parent) and history component (child) are subscribed for the currentCount. In the customer component, when the user clicks the increase button, the increase function is executed, the value of the count is changed and this new value is broadcast to the app component and history component which are not directly connected to the customer component. So by using a common service class, we can define a common variable and share and change its value from other components.

Conclusion

In this article, we talked about what is component interaction, how the Angular application is structured, and how components interact with each other. There are 3 types of component interaction: Parent-to-child interaction uses an Input decorator for passing data, Child-to-Parent interaction uses an Output decorator and EventEmitter dispatch, and finally, Non-related components share data between them using a common service.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Piriyalini Niththiyanantham

Piriyalini Niththiyanantham

Undergraduate, Faculty of Information Technology, University of Moratuwa