This post how to send messages from multiple Angular components using the same EventEmitter. We have three parts – AppComponents, AnotherComponent, and YetAnotherComponent. The setup is usually hierarchical, where we embed the selectors of AnotherComponent and YetAnotherComponent in AppComponent’s HTML. We also have a service that holds an instance of EventEmitter.
For those new to Angular, there is a simpler version of the codes that only involve parent-child components.
Multiple Angular Components
We have three Angular components that have a reference to the TestServiceService service, a very hard-working service! 🙂
Before going to the Angular service codes, let’s review the components’ codes first. For the AppComponent, we set the default message and a way for it to set the message to its original value.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | import { Component } from '@angular/core'; import {TestServiceService} from './shared/test-service.service'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'ComponentCommViaEventEmitter'; message = 'Message From AppComponent' constructor(private testService: TestServiceService) { this.testService.eventEmitter.subscribe((data: string) => { this.message = data; }); } onClick() { this.testService.eventEmitter.emit('Message From AppComponent'); } } |
Then, we have the Angular component AnotherComponent, which has an onClick function to send a different message to AppComponent using the shared service that has the EventEmitter.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | import { Component, OnInit } from '@angular/core'; import {TestServiceService} from '../shared/test-service.service'; @Component({ selector: 'app-another', templateUrl: './another.component.html', styleUrls: ['./another.component.css'] }) export class AnotherComponent implements OnInit { constructor(private testService: TestServiceService) { } ngOnInit() { } onClick() { this.testService.eventEmitter.emit('Message from AnotherComponent'); } } |
YetAnotherComponent
Lastly, we have the YetAnotherComponent that sends a different message to AppComponent.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | import { Component, OnInit } from '@angular/core'; import {TestServiceService} from '../shared/test-service.service'; @Component({ selector: 'app-yet-another', templateUrl: './yet-another.component.html', styleUrls: ['./yet-another.component.css'] }) export class YetAnotherComponent implements OnInit { constructor(private testService: TestServiceService) { } ngOnInit() { } onClick() { this.testService.eventEmitter.emit('Message from YetAnotherComponent'); } } |
The service looks relatively simple. It only holds a reference to an instance of EventEmitter. Then, the Angular components share this single instance of EventEmitter to communicate with each other.
1 2 3 4 5 6 7 8 9 | import {EventEmitter, Injectable} from '@angular/core'; @Injectable({ providedIn: 'root' }) export class TestServiceService { eventEmitter = new EventEmitter<string>(); constructor() { } } |
Our app.module.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppComponent } from './app.component'; import { AnotherComponent } from './another/another.component'; import {TestServiceService} from './shared/test-service.service'; import { YetAnotherComponent } from './yet-another/yet-another.component'; @NgModule({ declarations: [ AppComponent, AnotherComponent, YetAnotherComponent ], imports: [ BrowserModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { } |
Testing Multiple Components With One EventEmitter
When we start the Angular application, we can test it by randomly clicking the buttons. The Angular components, service, and the instance of EventEmitter work their magic! We can notice that the message changes when we click a different button.
By the way, we are using Angular 8.