Data communication between components siblings or from Parent to child or vise-versa is possible by using many ways in Angular applications.
Sometimes we may need to pass data or any information to parent component from any of its child components in its hierarchy. For example, we have messages component which shows unread messages, now if we want to display the count on the header component.
In that case, we have two options available to do so. The EventEmitter available in angular core package and RxJS Subject provides observable which can be used to emit values to other components.
Using Angular Core’s EventEmitter
The EventEmitter
class which is a part of @angular/core package can emit the data to we can subscribe to in parent component.
This is a traditional old approach we used to use in Angular for passing on data or emit
to parents and can observe the change using the subscribe
method.
Using RxJs <em>subject</em>
The RxJS Subjects also works in a similar way and implementation is also a way more identical like EventEmitter but they are more preferred.
In subjects, we use the next
method to emit values instead of emitting.
The subject is a special kind of observable which is more active as the next
method is exposed directly to emit values for observable.
In our quick example, we will discuss both methods for which we will create a new child component SendMessageComponent which will emit string message to the app’s main component for which we also need a service.
Let’s quickly implement one by one…
Create a new Service
To implement in a better way we will use a service that is a good practice we can follow in a real application.
Run following ng generate
command to create a new service in the services folder:
$ ng g service services/send-message
Above command will create the following service:
// send-message.service.ts
import { Injectable, EventEmitter } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class SendMessageService {
constructor() { }
}
Auto-generated service is already having the providedIn
set to 'root'Â
if you want to set it in app.module.ts file’s providers
array then it’s also fine.
 The EventEmitter method:
To use EventEmitter just create a new instance of it to a variable messageEmitter
to keep instance, which will accept String
, you can set any type for data you want to emit.
The EventEmitter is available in the angular core package we need to import first.
// send-message.service.ts
import { Injectable, EventEmitter } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class SendMessageService {
messageEmitter = new EventEmitter<String>();
constructor() { }
}
Emit Value
Now from the SendMessageComponent
component we will emit value using the above service.
Add a button with method sendMessage()
to send string value using emit method as shown below:
In the send-message.component.html file add button
<button class="btn btn-primary" (click)="sendMessage()">Send Message</button>
update the send-message.component.ts file with following code:
// send-message.component.ts
import { Component, OnInit } from '@angular/core';
import { SendMessageService } from 'src/app/services/send-message.service';
@Component({
selector: 'app-send-message',
templateUrl: './send-message.component.html',
styleUrls: ['./send-message.component.css']
})
export class SendMessageComponent implements OnInit {
constructor(
private sendMessageService: SendMessageService
) { }
ngOnInit() {
}
sendMessage(){
this.sendMessageService.messageEmitter.emit('Message From Child Component');
}
}
Get Emitted Values
We are getting the emitted values in app.component.ts file using the service variable messageEmitter
which returns an observable.
In the ngOnInit()
hook we will put this observable and feed its value in the local variable messageToShow
:
// app.component.ts
import { Component, OnInit } from '@angular/core';
import { SendMessageService } from './services/send-message.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit{
title = 'angular-eventemitter-and-subject-demo';
messageToShow:String;
constructor(
private sendMessageService: SendMessageService
) { }
ngOnInit(){
this.sendMessageService.messageEmitter.subscribe(msg=>{
this.messageToShow = msg;
})
}
}
That’s it now if users click on Send Message button in child component it will emit the string value using service to app component.
Now we will check how to convert EventEmitter with RxJS Subject.
The Subject Method:
To use Rxjs Subject we only need to make changes at just two places:
1) In the SendMessageService replace
messageEmitter = new EventEmitter<String>();
with
messageEmitter = new Subject<String>();
where we need to import Subject
from rxjs:
// send-message.service.ts
import { Injectable,
// EventEmitter
} from '@angular/core';
import { Subject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class SendMessageService {
//messageEmitter = new EventEmitter<String>();
messageEmitter = new Subject<String>();
constructor() { }
}
2) In the SendMessageComponent
we need to use next()
instead of emit()
:
// send-message.component.ts
import { Component, OnInit } from '@angular/core';
import { SendMessageService } from 'src/app/services/send-message.service';
@Component({
selector: 'app-send-message',
templateUrl: './send-message.component.html',
styleUrls: ['./send-message.component.css']
})
export class SendMessageComponent implements OnInit {
constructor(
private sendMessageService: SendMessageService
) { }
ngOnInit() {
}
sendMessage(){
//this.sendMessageService.messageEmitter.emit('Message From Child Component');
this.sendMessageService.messageEmitter.next('Message From Child Component');
}
}
That’s its that simple 🙂
Leave a Reply