Sharing Data between Components using Service in Angular

Sending Notifications from one single component to other components using a Service in Angular and Also implement SnackBar to display messages from Angular Material Library

Hiten Sharma
6 min readApr 10, 2020

Sharing data between components can be sometimes becomes difficult.

As you need to update data on click events from one component and get data from another component and then reflecting the changes on same component.

In this tutorial we will learn how to share data between components using a Service, to be more specific how we can show notifications for component communication in DOM using a Snackbar module from Angular Material UI component library. We will learn concept of Subject and how we can use it for components communication.

You can find link to full code at the end of this article.

Let’s say we have 2 components Message Component and Output Component that may or may not be related, they can be parent, child, siblings or not at all related but they share a same instance of service.

Goal

We want to send notifications from Message Component to Output Component or any other component. This is the final goal we want to achieve.

Goal

We cannot use EventEmitter class as component may not be related and also if they are related there is a lot of hierarchy we need get through which makes code difficult to maintain. Instead we will be using special type of Observable Known as Subject.

A subject is an Observer and an Observable, in simple words a subject involves taking the notifications from single source and forwarding them to one or more destinations. A subject is usually placed in a Service.

The output Component will send the variable value true to the Subject and Subject will update this variable from false to true in the Message Component and the notifications will be shown in the output component.

Setting Up Environment

First, We will create a new Angular Project and then add Angular Material UI component Library for beautiful User Interface and use Snackbar module to show notifications. We will create Message Component and a Message Service and app Component(Default) will act as Output Component.

Final Result will look like:

Let’s Dive into Code!

Creating a new Angular Project

We will create a new angular project for that and make use of angular-cli for this project. Make sure you have already installed node and npm on your machine. Open Command Prompt(cmd) and navigate to the desired location. Enter the following command in cmd.

ng new share-messagee-between-components

External Dependencies

Include Angular Material UI component Library in your Angular Project for beautiful User Interface. It will ask for some user input, but you can simply press Enter.

ng add @angular/material

Creating Message Component

We will create Message component using angular-cli. To generate new component type following command:

ng g c Message

Creating Message Service

Now we will create new Message Service using angular-cli. To generate new Service type following command:

ng g s Message

Creating Subject in Service

First step is to create a subject and expose subject as an observable in the service. A subject act as an source from where the notifications are sent to other components.

private _successMsgSource = new Subject<boolean>();

Next we expose Subject as an Observable. The right convention for declaring observable is to append a $ sign

successMsg$ = this._successMsgSource.asObservable();

And then creating a method which accepts the value from the Output Component and pushes that value using an observble.

sendSuccessMsg(message: boolean) {this._successMsgSource.next(message);}

Complete service.ts file

import { Injectable } from "@angular/core";import { Subject } from "rxjs";@Injectable({providedIn: "root",})export class MessageService {constructor() {}private _successMsgSource = new Subject<boolean>();successMsg$ = this._successMsgSource.asObservable();sendSuccessMsg(message: boolean) {this._successMsgSource.next(message);}private _errorMsgSource = new Subject<boolean>();errorMsg$ = this._errorMsgSource.asObservable();sendErrorMsg(message: boolean) {this._errorMsgSource.next(message);}private _uploadedMsgSource = new Subject<boolean>();uploadedMsg$ = this._uploadedMsgSource.asObservable();sendUploadedMsg(message: boolean) {this._uploadedMsgSource.next(message);}private _uploadFileExistMsgSource = new Subject<boolean>();uploadFileExistMsg$ = this._uploadFileExistMsgSource.asObservable();sendUploadFileExistMsg(message: boolean) {this._uploadFileExistMsgSource.next(message);}}

Sending Value from Output Component to service

Second step is to send message from Output Component to the service. Now we send notifications on clicking of button and call different methods. We will also call “openSnackBar()” method to open a Snackbar on button click.

Complete app.component.html

<mat-card><h1>Sharing Messages Data between Components</h1><div><buttonmat-raised-buttoncolor="primary"(click)="openSnackBar()"(click)="successMsg()">Success Message</button><buttonmat-raised-buttoncolor="primary"(click)="openSnackBar()"(click)="errorMsg()">Error Message</button><buttonmat-raised-buttoncolor="primary"(click)="openSnackBar()"(click)="uploadFileExistMsg()">File Exist Message</button><buttonmat-raised-buttoncolor="primary"(click)="openSnackBar()"(click)="uploadedMsg()">Upload Message</button></div></mat-card>

Let’s define this methods in class. The methods will call sendSuccessMsg() from the Message Service and passing the argument true to the method.

We will Inject Service in the constructor of the component. Also we will Inject MatSnackBar Module. Also import the service MatSnackBar as well.

Complete app.component.ts File

import { Component, OnInit } from "@angular/core";import { MessageService } from "./services/message.service";import { MessageComponent } from "./message/message.component";import { MatSnackBar } from "@angular/material";@Component({selector: "app-root",templateUrl: "./app.component.html",styleUrls: ["./app.component.scss"],})export class AppComponent implements OnInit {title = "share-messagee-between-components";ngOnInit() {}durationInSeconds = 1; //Snackbar duration in seconds to be shown on screenconstructor(private _snackBar: MatSnackBar,private _msgService: MessageService) {}//Snackbar MethodopenSnackBar() {this._snackBar.openFromComponent(MessageComponent, {duration: this.durationInSeconds * 1000,});}//Message Methods sending the variable value to serviceerrorMsg() {this._msgService.sendErrorMsg(true);}successMsg() {this._msgService.sendSuccessMsg(true);}uploadedMsg() {this._msgService.sendUploadedMsg(true);}uploadFileExistMsg() {this._msgService.sendUploadFileExistMsg(true);}}

Adding Styling

Adding Basic Styling to the Component:

Complete app.component.scss file

h1 {text-align: center;}mat-card {flex-direction: column;margin: 1rem;width: 70vw;background-color: #f2f5f7;display: flex;height: 50vh;justify-content: space-between;div {display: flex;justify-content: space-evenly;align-items: center;}mat-card-actions {margin-bottom: 0;}}

Note: If an error occurs during the compilation of code add below line of code in app.module.ts file

providers: [],bootstrap: [AppComponent],entryComponents: [MessageComponent],

Subscribing to the Observable

The Final Step is to subscribing to the observable in the Message Component. So head over to message.component.ts file and since we are making use of Subject asObservable that is defined in the service, so let’s begin by injecting Service. Also make sure to import it.

import { MessageService } from "../services/message.service";constructor(private _msgService: MessageService) {}

Generally we subscribe to observable in the OnOnit Lifecycle Hooks

ngOnInit() {this._msgService.successMsg$.subscribe((message) => (this.successMsg = message));

Updating the value of successMsg variable from false to true when a method is called.

Complete message.component.ts file

import { Component, OnInit } from "@angular/core";import { MessageService } from "../services/message.service";@Component({selector: "app-message",templateUrl: "./message.component.html",styleUrls: ["./message.component.scss"],})export class MessageComponent implements OnInit {successMsg: boolean = false;errorMsg: boolean = false;uploadedMsg: boolean = false;uploadFileExistMsg: boolean = false;constructor(private _msgService: MessageService) {}ngOnInit() {this._msgService.successMsg$.subscribe((message) => (this.successMsg = message));this._msgService.errorMsg$.subscribe((message) => (this.errorMsg = message));this._msgService.uploadedMsg$.subscribe((message) => (this.uploadedMsg = message));this._msgService.uploadFileExistMsg$.subscribe((message) => (this.uploadFileExistMsg = message));}}

Now we call variable in DOM and only show a particular notification when the value of that variable is set to true using *ngIf directive.

Complete message.component.html file

<span class="example-pizza-party"><div class="successMsg" *ngIf="successMsg">Message sent successfully</div><div class="errorMsg" *ngIf="errorMsg">Something went wrong</div><div class="uploadedMsg" *ngIf="uploadedMsg">Files Uploaded successfully</div><div class="uploadFileExistMsg" *ngIf="uploadFileExistMsg">File already exists. Please choose a different File.</div></span>

Adding Styling

Now we will show different colors for different messages i.e for success message — green, error message — red etc.

Complete message.component.scss file

.successMsg,.uploadedMsg {color: green;}.errorMsg,.uploadFileExistMsg {color: red;}

Output:

Output

That’s it! We’re Done!

You can find the full source code on

Download source code on: GitHub🚀

Test it live on: Stackblitz🚀

References

Angular

RxJS

Your feedback is welcome!

If you enjoyed this article, please clap for it or share it. Your help is always appreciated.

--

--