Every project needs a loading indicator. Routes need to be able to call it. Service calls need to have access to it while fetching data. People are happier when they know something is happening, but that something is not finished yet. So what is the best way to make one? I think a good singleton service will get the job done.

So what do I mean by singleton service in Angular world? Here I am talking about a service instance that is shared across components. Think one service with a given state shared across any component that imports and references the service in its constructor.

Taking a step back to develop a mental model. Components get access to service through Angular’s dependency injection system. Angular goes with a hierarchical DI system (read more here). Angular asks you to think about it as if all component have their own injector. What gets injected into a component depends on the components provider settings as well as the providers of the parent components higher in the overall component tree. So there is the catch; components inherit the service instance of their parent (or parent’s parent and on up). But, if a component adds a service reference to its list of providers that the parent also injects, a new service instance will be instantiated that does not share state with the parent’s service.

So that is kinda weird, but it also allows for us to segment our services to component trees and ngModules (because ngModules have injectors too). Two different ngModules may need a service but need two separate instance of it. All that is needed is a reference in the ngModules provider for each module and then you have two separate singleton. So I guess its not really a singleton, but its not a cluster, so I guess is just two singletons. The singleton name is not perfect, but once you understand Angular’s hierarchical DI system all is well.

So how does this apply to a loading indicator? Well we want a service that is at the very top of app so that any component that calls it can display an indicator when loading anything. We will have a show method and a hide method. If two components call for the show method we will wait for two hide calls to hide the indicator. That’s about it.

In the component file we need a RxJS subscription to hold the state from the service. Notice how we do not have any provider for the component. Our template conditionally renders the loading indicator based on the subscription state.

Some styles for rendering in the middle of the page

Next we have our service. Here we create a RxJS subject observable that will push any state changes to the subscribers. We also have our methods to control the loading indicators state. The counter tracks the number of calls so that the loading indicator is only hidden when all of the calls are resolved.

Now we have a component that can be added to our ngModules. We want to provide the service at the top level ngModule. This will give the entire tree underneath the same service instance. Now we just need to call the show method in a component before we go get data and when we have it back, call hide.