Introduction
The Observer design pattern is one of the most important design patterns in the GoF book and this article shows how it can be used to facilitate broadcast messaging in Angular. Broadcast messaging means that a sender, the Publisher, sends messages to several receivers, the Subscribers. Any component can via the Publisher send messages to any other component subscribing to the Publisher Service.
Background
In Angular, it’s easy to send messages between Parent and Children components. This is standard procedure in any Angular application. However, to make any component send messages to any other component anywhere in the component hierarchy can be hard. The code in this article contains the bare minimum of what's needed to illustrate the principle and I have tried to make the code clean and short. The application from where the code is fetched is based on Angular2 version 8.
The Publisher Service
The Publisher Service is a Singleton class using the rxjs npm package and looks like this:
import * as Rx from 'rxjs';
import {InformationToShow} from '../models';
export class PublisherService{
private instance: Rx.Subject<InformationToShow>;
createInstance(): Rx.Subject<InformationToShow> {
const instance = new Rx.Subject<InformationToShow>();
return instance;
}
public getInstance(): Rx.Subject<InformationToShow> {
if (!this.instance) {
this.instance = this.createInstance();
}
return this.instance;
}
}
The model class InformationToShow
may look like this:
export class InformationToShow{
Information: string;
SubscriberId: number;
...
}
This class can be extended and changed in any way you want. SubscriberId
is used to make it possible to send messages to a particular component even though all subscribers receive the same message.
The Subscribers
The Subscribers are the components listening for and acting on changed information by subscribing on the Publisher Service. Imagine that there are many instances of this code in the application. Each instance has its own SubscriberId
to make it possible to send messages to a particular instance even though all instances receive the same message. The Publisher Service is injected via Angular constructor dependency injection like all other services in the application:
constructor(private publisherService: PublisherService) { }
In ngOnInit
, the service is subscribed to like this:
publisherSubscription: any;
ngOnInit() {
this.publisherSubscription = this.publisherService
.getInstance().subscribe((data: InformationToShow) => {
if (data.SubscriberId === this.information.SubscriberId)
{
this.information = data;
}
});
}
Here, you see how SubscriberId
can be used to make sure that only information belonging to a particular instance is taken care of by the component.
Send Messages From Anywhere in the Program
To send messages, the method getInstance().next(informationToShow)
is used, like this:
onInformationChange(informationToShow: InformationToShow) {
this.publisherService.getInstance().next(informationToShow);
}
}
Imagine that this code can be used in many places in the application, thus facilitating many-to-many communication.
At last, unsubscribe in ngOnDestroy()
:
ngOnDestroy() {
this.publisherSubscription.unsubscribe();
}
History
- 16th November, 2019: First version
- 19th November, 2019: Added
unsubscribe