Angular developers all over the world have one thing in common. They strive to write code that isn’t hard to maintain. We all truly know that spending more time writing code in the first place is much better than having to come back to it 2 months later.
I find that making code generic helps maintainability. As a result, most of the time I’m writing new code, rather than refactoring old code.
One of the first things that I remember doing in Angular, was working out the full interaction between components, services and APIs.
I’m going to help you identify a great way of component – service interaction. But in addition, it will serve as a way of helping you understand some Angular principles. From structuring your application to displaying data in your components.
So, this article will address a variety of different principles:
- Environment files
- HTTP & API Services
- Types and being strict
- Observable & RxJS operators
- Displaying data with Angular’s async pipe
First of all, we’ll need to get the prerequisites out of the way.
Let’s get started.
Setting up our Angular Application
- Installing Node & NPM package manager
- Installing Angular
- Creating & setting up our application
We need to install Node & NPM. Head to https://nodejs.org/en/
Once you have installed Node & NPM, you can then install Angular’s CLI.
npm install -g @angular/cli
We’ll first need to initialise our new project.
ng new blog-entries-src --defaults
Making sure that you’re in the project directory, we can finally start our application. The open flag is optional. It will open the application in your browser.
ng serve --open
Using Angular environment file
Storing configuration values in environment files makes a lot of sense. In your development environment you will be using a different API than in your production environment. It’s just good practise. You don’t want to be messing with your production data in your development environment.
That means no hard coding things that are likely to change in a different environment – it causes a lot of misery!
To do this, we can modify the environment object in:
Modify the file to:
Once we have created an API, we can replace the URI with our own.
Now we have that setup, we can jump straight into creating our API Service.
Creating an API Service
Angular provides its own solution to an API/HTTP service. It provides us with HTTPClient, but I think we can improve on this. What we’ll be doing, is creating a wrapper service that provides us with a little more utility than what HTTPClient does.
We first need to import the modules that we’ll require for this. Note that we’re importing HttpClientModule. Your app.module.ts file should look like :
In addition, we need to create a new service that will act as our HTTP service wrapper. We’ll skip adding test files for now. Create the following directory & file.
Our API service will look like the following:
Our get method is the most interesting piece of code. The get method allows us to describe the type of data we expect. I have found that following strict type conventions has made developing much easier, especially when it comes to:
- Catch errors easily
Why should you type data?
Angular as a framework really tries its best to implement rock solid principles, and Typescript is its best hope at achieving this. You should type your data as much as you can. Rarely do I use JSON data directly from an API. Strict types are powerful, try to use them!
Creating our Resource Model
Now that we have API service setup, let’s create a resource we can use in our application.
Firstly, let’s create another directory, with a file:
In that file, we will define our BlogEntry model. We’ll keep it pretty basic for now.
We’ve created a class called BlogEntry. It has 3 private attributes: _id, _heading and _preview. We provide a getter and setter for each of these attributes.
This is what is known as encapsulation.
Encapsulation allows us to implement “data-hiding” and “data-modifying” restrictions. We can define what can be modified, and what can be read. It’s one of the fundamentals of Object Oriented Programming.
Creating a factory
I normally create factories and use them to type loose JSON into strongly typed Objects. I find this particularly important when we require to maintain state of a model. Typed reference data is much easier to work with.
Create a new directory and file as follows:
That file will look like:
We’re taking in JSON as the parameter, and we’re outputting a strictly typed Object. We do this by create a new instance of a BlogEntry, set the attributes and return the Object.
Why are we doing this?
When I see code creating new instances of types directly in the Components or Services, I ask myself why! Centralising this procedure makes so much more sense, as the desired behaviour should be the same every time. Above all, it keeps our code readable & maintainable.
Creating a resource service
Now that we have a factory and a resource model setup, we need some data. Following that, we will create a service to retrieve it.
Creating some data
We’ll create a JSON file, with some dummy data. In other words, we don’t have an API setup, so we will have to mock our data.
Create a file as follows:
This file will contain some dummy data, related to blog entries.
Creating a service to retrieve our resource
Now that we have created some mock data, we just need to retrieve it. In our service directory, we will create a file:
The file will look like:
First off, we inject our service we wrote earlier into this one. Anywhere we need direct access to our API, we will inject our ApiService.
constructor(private api: ApiService)
We’ll use the get method that we created, passing /assets/blog-entries.json in as our endpoint. This, combined with the URI we set in our environment file, will allow us to retrieve our blog entries with an HTTP request.
Using RxJS to manipulate our data
We’re using RxJS’s operators to manipulate the data, before it is returned back.
We want the data to be returned as strictly typed data, that being an array of BlogEntry objects.
We use the pipe operator to achieve this.
- pipe is a method available on Observable types. It allows us to compose multiple operators. We use the map operator in this instance, but we could use any operator, just like:
The above code will use the flapMap operator to create BlogEntry objects one at a time. The filter operator will then proceed to filter out all entries, where the attribute headings does not contain Angular. Each entry that matches our filter will be published to a subscriber.
- map is a common operator. It is used to apply projection with each value from a source. In this case our source is data, and our projection is transforming each entry in data into a typed BlogEntry.
It’s important to note that in our service we’re using RxJS’s map operator to apply a projection to our data. We are also using Array.map to iterate through our array and transform individual objects to strict data.
Using a component to show our data
Finally, and most importantly, we are ready to present our data. Let’s create a new component.
Let’s separate our components into a new directory:
Now in that directory, we can use Angular CLI to generate our component:
ng generate component blog
The job of our component will be simple. It will display our blog entries.
We can achieve this in multiple ways. For instance, we could manually subscribe to the blog service’s getBlogEntries method. Or, more simply we could use Angular’s async pipe. For simplicity, we’ll use the async pipe. There are advantages and disadvantages to both, but that’s a subject for a different time.
Our component will be very simple, almost too simple. Our script file will look like:
All we’re doing here, is injecting our blog service. We are then assigning our services method to our component’s scope variable $blogEntries. The method returns an Observable with data typed as BlogEntry.
Our HTML template will be as follows:
We’re very close to finishing. All we need to do, is insert our blog component’s selector in app.component.html. As below:
That’s it! You should now be able to see data on your page, like so:
That’s it! We now have blog entries displaying on our page. You can take a look at the styling I used in the projects Github repository.
In conclusion, we have applied a bunch of fundamental techniques together, to create something pretty clean & well cut!
- Use environment files for their purpose
- Creating a wrapper API service that always targets the correct URI. Allows our other services to be specific to their purpose.
- Type your data! Use Angular & Typescript the way it was supposed to be used. Create models, and be strict. Trust me, it helps a ton.
- RxJS is a powerful tool – make use of it!