Ok! So we’ve learned how to get started with an Angular 4 application and we’ve written our first component. The next things you are going to learn about are services and dependency injection.
In the previous example, we had a UserListComponent where we initialized an array of users. But your component shouldn’t know or care about where the list of people is coming from being its local storage, a database, a web service.
That’s why we are going to extract that data access logic into a service that we’ll inject into our component through its constructor. Breaking application into smaller pieces that have a single responsibility, will make it much easier to work, more maintainable, and reusable.
So this is how our UserListComponent looks right now:
Our job is to extract the data access logic into a separate UserService service that will encapsulate that responsibility of retrieving people from wherever people come from and provide that as a service for the rest of the application.
Our current data access logic is super simple, we are just instantiating an array and that’s it, but in the very near future we will be using a service, so bear with me.
What are Angular Services?
Every application is composed of a lot of subsystems that do different things like logging, data access, caching, specific application domain knowledge, etc. Depending on the type of application that you are building or the framework that you are using there are different ways to represent these subsystems.
Angular 4 uses the concept of services, an Angular service is a class that encapsulates some sort of functionality and provides it as a service for the rest of your application.
If you have an AngularJS background you’ll welcome this simplification in the Angular conceptual model: there’s no more service/factory/constant/provider conundrum. In Angular 4 there are only services, and they are just vanilla ES6 classes.
How to create an Angular Service?
Let’s create our new UserService in a new file user.service.ts. We’ll take advantage of the Angular CLI generators and run the following command:
ng generate service user
This will create an empty service called user.service.ts that will look like this:
Now if we extract the data access code from our UserListComponentinto the service we’ll get the following:
As you can see above this is just a simple ES6 class that exposes a getAll method which returns a list of persons.
Injecting Our User Service in The User List Component
Now that we have a service that encapsulates user data access we can use it from our UserListComponent. We will take advantage of dependency injection and inject the service through the component’s constructor.
What is Dependency Injection?
Real world applications do a lot of things.
In order to manage this innate complexity of real-world systems, we break them down into smaller subsystems that ideally do one thing or a teeny set of things.
As a result of that, we have a simpler system made up of small components that depend on each other. Initially, we may have these as hard-set dependencies (for instance, using the new operator to instantiate them), but we want these dependencies to know the least amount of information possible about each other. We want each subsystem to depend on abstractions and not concrete implementations.
Why? Because that way we can create systems that are more flexible, extensible and sturdy where changes in concrete implementations don’t propagate to other parts of the system.
So we have these nice collections of subsystems that depend only on abstractions. But… How are we supposed to work with them and create a real program out of them? Or, what is the same, how can we make them use the real dependencies at runtime? Well, that’s where dependency injections come in. It’s the mechanism by which we can introduce real implementations to these subsystems that can do real work at runtime.
Using Angular 4 Dependency Injection to Inject Our User Service in the User List Component
We start by importing the UserService from the user.service module and then we inject it into the UserListComponent via its constructor:
If you had your http server running (if you don’t run ng serve –open) you’ll see that… it didn’t work!!
Open your browser dev tools and you’ll discover the following error message:
No provider for UserService! (UserListComponent -> UserService)
That Means Angular 4 doesn’t know how to inject a UserService into UserListComponent. Let’s see how to do that.
Registering Your Service With Angular 4
In order to register a service with Angular 4 you use the providers property within the Component decorator. For instance, to make the UserServiceavailable throughout our app we can register it within the AppComponentcomponent. This will make it available to this component and all its children (like UserListComponent).
We start by importing the service from its module and adding it to the provider’s property within the Component decorator of AppComponent.
You Can Also Register Services at the Module Level
With the NgModule decorator after RC5 and the new concept of Angular 4 Modules you can now register services to be used throughout a whole module. You can achieve that via the providers property of the NgModule decorator:
When would you want to do that?
– you may wonder. Well, whenever you want to use the same instance of a service for your whole application (which is a very common approach).