Dependency Injection in Angular

Ege Aytin
4 min readMay 16, 2020

--

One of Angular's most powerful features as a framework is how it brings the dependency injection with typescript. Dependency Injection or for short as DI is a core concept of Angular and simply allows classes to receive dependencies from another class. In this article, we will look at; Angular Service structure, @Injectable() decorator, component-service relationships. The outcome is understanding how we can handle dependency injection in our Angular projects.

Firstly, we should examine the basic concept of Services to better understand the dependency injection in Angular.

Services in Angular

If you used any of the other frontend frameworks you should familiar with the concept of services and their logic. In Angular, service is basically a class that can be used by multiple components. We can use services for multiple purposes. For example; to outsource some code that you want to use in multiple components, accessing and utilizing API for handling necessary business needs for your project or even you can use them to manage your data in one global place where the multiple pieces or spots in our application have to use.

We may go over a circumstance where we need some code to be utilized everywhere on the project. It tends to be for data connection that should be shared across components, and so forth. Services assist us with accomplishing that. With services, we can access commonly used methods and properties across different segments of the entire project.

To create a service, we need to make use of the command line. The specific Angular CLI command for creating service is:

ng generate service demo

After execution of the above command we will get “demo.service.ts in our app directory as followed syntax:

import { Injectable } from '@angular/core';

@Injectable({
providedIn: 'root'
})
export class DemoService {

constructor() { }
}

@Injectable() decorator

As you can see that our DemoService imports the Angular Injectable symbol and annotates the class with the @Injectable() decorator. It denotes the class as one engaged with the method for dependency injection.

You must make any service available to the dependency injection system before Angular can inject it into any component by registering a provider. A provider is something that can produce or deliver a service. For this situation, it instantiates the DemoService class to provide the service.

By default, the Angular CLI command ng creates service registers a provider with the root injector for your service by including provider metadata, that is providedIn: ‘root’ in the @Injectable() decorator.

The @Injectable() decorator acknowledges a metadata object for the service, a similar way the @Component() decorator accomplished for your component classes.

@Injectable({
providedIn: 'root'
})

At the point when you provide the service at the root level, Angular makes a solitary, shared instance of DemoService and injects into any class that requests it. Enlisting the supplier in the @Injectable metadata additionally permits Angular to streamline an application by evacuating the service in the event that it turns out not to be utilized.

Accessing to our Service in a Component

Firstly let's add some test data and a related get method to our service for component usage:

import { Injectable } from '@angular/core';

@Injectable({
providedIn: 'root'
})
export class DemoService {
tasks = [
{ id: 10, title: 'Refactor Code'},
{ id: 11, title: 'Submit Report'},
{ id: 15, title: 'Send PPT'},
{ id: 18, title: 'Skype Tommy'}
]

constructor() { }

getTasks() {
return this.tasks;
}
}

Now pretend like our purpose is reaching task dataset in any of our components. But How? Let's say we have a demo component with tasks property that we want to assign it to the DemoService task dataset.

import { Component, OnInit } from '@angular/core';

@Component({
selector: 'app-demo',
templateUrl: './demo.component.html',
styleUrls: ['./demo.component.scss']
})
export class DemoComponent implements OnInit {
tasks = []
constructor() { }

ngOnInit(): void {
}
}

Notice that in our DemoComponent.ts file we have ngOnInit method. It is the safest place for using our service to get data because; this method is executed when Angular creates this component. More deeply, when It's executed ones; all component related properties are initialized so that's why it is the safest place for assigning returning service values to components properties. But in order to use DemoService in the ngOnInit method, we need to access it first.

We can access our DemoService from our DemoComponent as below,

import { Component, OnInit } from '@angular/core';
import { DemoService } from '../demo.service.ts'

@Component({
selector: 'app-demo',
templateUrl: './demo.component.html',
styleUrls: ['./demo.component.scss']
})
export class DemoComponent implements OnInit {
tasks = []
constructor(private serviceInstance: DemoService) { }

ngOnInit(): void {
}

}

Which we also need to import DemoService at the top of this file. With this easy setup, Angular will automatically recognize constructor property and create a DemoService instance for us. We call it “serviceInstance” above.

Now we are ready to go! We will now use the getTasks method for getting our task dataset and assign it to our tasks variable as follows.

import { Component, OnInit } from '@angular/core';
import { DemoService } from 'src/app/demo.service.ts'

@Component({
selector: 'app-demo',
templateUrl: './demo.component.html',
styleUrls: ['./demo.component.scss']
})
export class DemoComponent implements OnInit {
tasks = []
constructor(private serviceInstance: DemoService) { }

ngOnInit(): void {
this.tasks = this.serviceInstance.getTasks();
}

}

To sum up, Angular has its own dependency injector and it is kind of a framework for handling the creation of instances of classes that we need in our application. As we need any kind of service in our specific component we can simply add a property of that service to our constructor. I hope now you understand how to handle dependency injection operations in your Angular projects. Cheers!

--

--

Ege Aytin

Product person, passionate about Golang and open source software. Building Permify, an open-source authorization service: https://github.com/Permify/permify