Let’s build a small application using Observable Data Services and Angular!
Building even small applications can be challenging if they involve asynchronous data. Data flow in particular can be difficult to solve. In this example, I would like to show how easy it is to fetch data from an API and present it to the user using Angular🚀 and Observables⚡️.
We are going to get the standings of top football leagues from football-data.org⚽️ and we will use RxJs Subjects🔥 to feed information through Observable Data Services to components.
It is important to have fancy modern-looking components so we import Angular Material into the project (and what is more beautiful than a stylish gradient going from purple to blue in the background right? 🦄). You can check the deployed application here and the public git repository here.
Let’s get started with generating an Angular project. If you do not have Angular CLI installed run:
npm install -g @angular/cli
then create a new project:
ng new football-standings
and finally add Material:
ng add @angular/material
At this point we need three folders for our components, models, and services so structure looks like this:
|-src
|--app
|—--components
|—--models
|---services
I am going to start with generating a service which will be called StandingService with the following command:
ng g s standing
As the title suggests we are going to use an Observable Data Service which means that an RxJs Subject will be used to emit values that will be received by the component. A Subject is a special type of Observable that can be used to emit values and can be also be subscribed to. This means that we can feed data into it and emit those values to any observers that are subscribed.
There is a reason I’m using a BehaviorSubject 🤘🏻 instead of a Subject here. A BehaviorSubject emits the previously emitted value to new subscribers. This can be really handy in an application. An example use case is fetching data from an API and emitting received value but only subscribing to the Subject after some time has passed.
This approach can solve race conditions 🏃🏻 in the event we are struggling to receive data quickly — for example during bootstrapping. Using this approach we still receive the previous value in case of a late subscription.
Notice that we initialize the BehaviorSubject but we expose it only as an Observable. The reason for this is to prevent emitting values outside the service and only allow values to be received on subscription.
This article does a great job of explaining Observable Data Services and especially the pitfalls that should be avoided.
At this stage, we will need an auth token for the API which can be obtained by registering here. The free tier of 10 calls/minute will be enough for us since we only need the top competitions and we won’t make a ton of requests.
To finish up our service we add the API endpoint, league codes, and a function which makes a `get` request for the standings for a given league. We are only looking for the total matches played, so we take only the first element of the standings array.
The only thing left to make the API call work is to add our auth token to the request header. I like using an interceptor in this case so if we decide to expand the application we do not need to add a token for each new request.
Our service is ready to fetch data and provide it, but we are really in need of a component that can consume it. Time to generate our standings component.
ng g c standings
First, let’s inject our service and make a request to get Premier League data when the component is initialized.
We inject the StandingService and initialize our teams$ observable. As you can see, Premier League standings are fetched initially but we also have a getStandings method in case we would like to fetch data from other leagues.
The last step in building the application is to add a table and enable users to select which league they want to fetch. First, we add a mat-select and listen to selection change events and call getStandings with the value when another league is selected.
Next, we need a mat-table to display the standings. Here we’re able to pass an observable to the table so we can present new data in case a new value is emitted.
To have our wonderful table ready we pass the $teams observable as a dataSource and define the columns.
At this point, all we need is to define the columns in our .ts file.
Finally, a finishing touch. We add the gradient background (🦄) and a header so the whole site feels a bit cozier. The CSS and header component is in the git repository if you’d like to achieve the same look. (Also do not forget to import the needed modules to app.module.ts!)
Aaand we’re done! We made a tiny fancy application that displays real-world data in record time! ☀️️