How to use Services to pass data between sibling component In Angular
Services can be used to pass data and components between parent and child components or between sibling components. We will take up an example to showcase how to pass values using services between child components.
We will create a service component to pass values. In the terminal, execute the following command –
ng generate service data-connect
It will create a service class file named data-connect.service.ts
Consider the following code changes –
<!--comp-alpha.component.html -->
<div style="
display: flex;
background-color: lightgreen;
padding: 1rem;
height: 20rem;
flex-direction: column;
margin: 2rem;
">
<div style="display: flex; flex-direction: row; justify-content: center">
This is alpha component
</div>
<div style="display: flex; flex-direction: column; justify-content: center">
<div style="
display: flex;
margin-top: 1rem;
margin-bottom: 1em;
justify-content: center;
">
<input type="text" name="alpaText" id="alphaText" [(ngModel)]="alphaText" />
</div>
<div style="
display: flex;
margin-top: 1rem;
margin-bottom: 1em;
justify-content: center;
">
Your Text - <b>{{ alphaText }}</b>
</div>
<div style="display: flex; flex-direction: row">
<div style="margin-left: 0.6rem; margin-right: 0.3rem">
<button>Pass to parent component</button>
</div>
<div style="margin-right: 0.6rem; margin-left: 0.3rem">
<button (click)="passToBeta()">Pass to beta component</button>
</div>
</div>
<div style="display: flex; flex-direction: column; padding: 0.5rem">
<div style="padding-top: 0.5rem; padding-bottom: 0.5rem">
<b>Whatever you see below is coming from parent component</b>
</div>
<div>{{ parentText }}</div>
</div>
<div style="display: flex; flex-direction: column; padding: 0.5rem">
<div style="padding-top: 0.5rem; padding-bottom: 0.5rem">
<b>Whatever you see below is coming from beta component</b>
</div>
<div>{{ dataService.getValue("alpha") }}</div>
</div>
</div>
</div>
<!-- comp-beta.component.html -->
<div style="
display: flex;
background-color: lightpink;
padding: 1rem;
height: 20rem;
flex-direction: column;
margin: 2rem;
">
<div style="display: flex; flex-direction: row; justify-content: center">
This is beta component
</div>
<div style="display: flex; flex-direction: column; justify-content: center">
<div style="
display: flex;
margin-top: 1rem;
margin-bottom: 1em;
justify-content: center;
">
<input type="text" name="alpaText" [(ngModel)]="betaText" id="betaText" />
</div>
<div style="
display: flex;
margin-top: 1rem;
margin-bottom: 1em;
justify-content: center;
">
Your Text - <b>{{ betaText }}</b>
</div>
<div style="display: flex; flex-direction: row">
<div style="margin-left: 0.6rem; margin-right: 0.3rem">
<button (click)="passToParent()">Pass to parent component</button>
</div>
<div style="margin-right: 0.6rem; margin-left: 0.3rem">
<button (click)="passToAlpha()">Pass to alpha component</button>
</div>
</div>
<div style="display: flex; flex-direction: column; padding: 0.5rem">
<div style="padding-top: 0.5rem; padding-bottom: 0.5rem">
<b>Whatever you see below is coming from alpha component</b>
</div>
<div>{{ dataService.getValue("beta") }}</div>
</div>
</div>
</div>
//data-connect.service.ts
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class DataConnectService {
constructor() { }
alphaValue: string = 'This is default alpha value';
betaValue: string = 'This is default beta value';
setValue(comp: string, _value: string) {
if (comp === 'alpha') {
this.alphaValue = _value;
} else if (comp === 'beta') {
this.betaValue = _value;
}
}
getValue(comp: string) {
if (comp === 'alpha') {
return this.alphaValue;
} else if (comp === 'beta') {
return this.betaValue;
}
return 'No component given';
}
}
//comp-alpha.component.ts
import { Component, Input, OnInit } from '@angular/core';
import { DataConnectService } from '../data-connect.service';
@Component({
selector: 'app-comp-alpha',
templateUrl: './comp-alpha.component.html',
styleUrls: ['./comp-alpha.component.css'],
})
export class CompAlphaComponent implements OnInit {
constructor(public dataService: DataConnectService) { }
alphaText = 'Hello alpha!';
ngOnInit(): void { }
@Input('textFromParent') parentText = '';
passToBeta() {
this.dataService.setValue('beta', "Hey there! I'm alpha component");
}
}
//comp-beta.component.ts
import { Component, EventEmitter, OnInit, Output } from '@angular/core';
import { DataConnectService } from '../data-connect.service';
@Component({
selector: 'app-comp-beta',
templateUrl: './comp-beta.component.html',
styleUrls: ['./comp-beta.component.css'],
})
export class CompBetaComponent implements OnInit {
constructor(public dataService: DataConnectService) { }
betaText = 'Hello beta!';
ngOnInit(): void { }
@Output() childButtonClicked = new EventEmitter<string>();
passToParent() {
this.childButtonClicked.emit('Button clicked in beta component');
}
passToAlpha() {
this.dataService.setValue('alpha', "Hey There! I'm beta");
}
}
In the data-connect.service.ts, we have created two variables to store values from the alpha and beta components respectively. Additionally, we have added two methods to get and set values of these two variables –
alphaValue: string = 'This is default alpha value';
betaValue: string = 'This is default beta value';
setValue(comp: string, _value: string) {
if (comp === 'alpha') {
this.alphaValue = _value;
} else if (comp === 'beta') {
this.betaValue = _value;
}
}
getValue(comp: string) {
if (comp === 'alpha') {
return this.alphaValue;
} else if (comp === 'beta') {
return this.betaValue;
}
return 'No component given';
}
We are injecting the service inside the alpha and beta components using the class constructor –
constructor(public dataService: DataConnectService) {}
We are calling the setter event when the button is clicked to set the value of the service variable as below –
passToBeta() {
this.dataService.setValue('beta', "Hey there! I'm alpha component");
}
Correspondingly, in the HTML component, we are getting the value using the following code –
<div>{{ dataService.getValue("alpha") }}</div>
The service we have declared is injected at the root level as declared in the component decorator meta-data.
@Injectable({
providedIn: 'root',
})
This means there is only one instance of service created at the root level and it is shared across all components. So any change in the service variable is reflected at all the places where the service is injected. So, this way, we can utilize the service for passing the data.
Output:
Component Communication in Angular
Angular, as a robust front-end framework, allows you to build complex and interactive web applications by creating reusable components. One of the key aspects of building such applications is effective communication between these components.
There are a lot of instances where we need to transfer data and events between angular components.
The communication can be between parent and child components or between sibling components. We will try out 3 methods to transfer data on our angular application.
Table of Content
- 1. Passing data from parent to child through input binding
- 2. Listening to events from the child component in the parent component
- 3. Using Services to pass data between sibling component