How to inform about something without using the state

State management libraries like NgRx or NgXS have become increasingly popular in recent years, and reasonably so: complex apps with large interconnected components and huge chunks of shared data require solid software to manage the state.

But sometimes we need something different: an event happened in one place of the application, and we want some other components to react to that event in a way that is not related to the state, and thus cannot be expressed as a change in state. Some examples may be:

A navigation event has happened and we want several components to update themselves for whatever reasons;

The user clicked on notification, and we want some other components to check if they need to be updated;

Some real-time event (like from a socket) happened and we need some components to check something;

And so on

As you see, this cases are not something state related, but more “event” related. We don’t have corresponding pieces of state to represent this things, and it would be disingenuous to try to reshape the state into something satisfying these constraints.

What we really want is an event stream / queue data type, that would broadcast events throughout the app. In this article, I am going to build one, which is not only extremely simple, but also fits any app regardless of its scale.

Event Types

First, we need to understand what types of events are there in our app. To have a simple overview of the events in our app, we will use a simple enum :

This is a simple example, but our app can have many more event types.

The payload

Sometimes just broadcasting that an event happened is not nearly enough. Sometimes there is also some data associated with the event. For example, in our “user clicked somewhere” scenario it is possible that one of the listeners will have to do something with the native click MouseEvent . So let’s implement a class that represents an app event:

This is very straightforward: this class represents what event happened (the type field) and what data is associated with that event (the payload event). Notice how this looks like redux (or some other state management libs) with their actions . The difference is we are not going to store this action results anywhere: just distribute it to subscribers.

The Event Queue itself

Here is a simple service that makes use of our actions:

We use a Rx.js Subject to propagate our events, define a method to listen to specific events and a method to dispatch one — very simple.

Usage

Now it’s time to test our service in the wild. Lets first dispatch some event from a component:

Nothing fancy here. And in another component we are going to listen to this event:

Well this was easy! In fact, because the on method of the EventQueue also returns an Observable , we can use pipe and do a number of awesome things with this! For example, we can trigger an HTTP request in one component every time an event fires (to update some local data, for example):

Bonus round

We can also extend the basic AppEvent class to get new events without having to provide the type property every time:

Summary

We now have a reliable way of communicating non state-related events and data associated with them throughout our Angular app.