Interested in Solving your Challenges with XenonStack Team

Get Started

Get Started with your requirements and primary focus, that will help us to make your solution

Proceed Next

Data Visualization

Angular Dependency Injection | A Quick Guide

Navdeep Singh Gill | 19 March 2025

Angular Dependency Injection | A Quick Guide
15:23
Angular Dependency Injection

Introduction to Angular Dependency Injection

Dependency Injection is a core part of Angular and one of its most significant features. It refers to a technique in which a class receives its dependencies from external sources rather than creating them. The dependencies being referred to here are the objects or services that a class needs, and so the Dependency Injection system is the technique by which a class requests these dependencies. In Angular, the Dependency Injection framework provides dependencies to a class upon instantiation, and classes receive the external logic without knowing how to create it.

All the Angular developers out there who are now moving on to React or the one who wants hands-on experience on React. Click to explore about, Learn React | Advanced Guide for Angular Developers

The critical benefactor of Dependency Injection is classes. Along with services, directives, pipes, components, and every such schematic in Angular, classes benefit from Dependency Injection in some way or another. When developing a small part of the application, such as a class, we might require external dependencies, such as an HTTP service that makes backend calls. In this case, one way would be to create our dependency whenever needed.

 

However, this approach has specific problems. First, it is tough to test. Second, this class knows how to create its dependencies, but it also knows about its dependencies. So, it is impossible to replace this dependency at runtime. Now, if we look at the alternate version of the code where the class does not know how to create its HTTP dependency and receives all the dependencies that it needs as input arguments, it becomes accessible to:

  • Replace the implementation of a dependency for testing.

  • To support multiple runtime environments.

  • To give new versions of a service to a third-party that uses our service in its code base, etc.

Why do we use Angular Dependency Injection?

One might consider why we use Dependency Injection in Angular and its core part. So, in more generic terms, dependency injection increases the flexibility and modularity of the applications. Using it in the application makes the code flexible, testable, and mutable. The benefits could be further explained in the following key points.

Loosely Coupled

With dependency injection, a component, such as a service, gets loosely coupled to the injected dependency. This just means that the component itself does not know how to create the dependency—in fact, it does not know anything about it. It just works with the dependency passed onto it.

Easier to Test

It becomes easier to test an injected component because it no longer depends on a specific implementation of the dependency, such as a service. It will work with any implementation of dependency that is passed on to it. We can create a mock service class and pass it while testing.

Component Reusability

Reusing the component becomes easier. Our component will work with any service or dependency with dependency injection as long as the interface is honoured. So, our component becomes testable, maintainable, etc., because of the Dependency injection pattern. But how do we create an instance of service and pass it to the element? That is what's done by Angular Dependency Injection.

An architecture containing tools, libraries, and functionalities suitable to build and maintain massive web projects using a fast and efficient approach. Click to explore about, Python Flask Framework

How do you build an Angular Dependency Injection framework from scratch?

Dependency injection in Angular is implemented by the Angular Dependency Injection framework that creates and maintains the dependencies and then injects them into the components, directives, or services.

 

The Angular Dependency Injection framework comprises five key players that work together.

  • Consumer: The class, i.e., Component, Directive, or Service that needs the dependency and to which the dependency is injected, is known as a consumer.

  • Dependency: The dependency is the service we want in our consumer or the actual code we want to inject.

  • Injection Token (DI Token): The Injection Token (DI Token) uniquely identifies something that we want to be injected, in other words, a Dependency. We use DI Token when we register dependency of our code.

  • Provider: The Providers maintain the list of Dependencies and their Injection Token, so it serves as a map between them. It uses the Injection Token to identify the Dependency.

  • Injector: An injector is a function that returns a dependency when a token is passed. It holds the Providers and is responsible for resolving the dependencies and injecting the Dependency to the Consumer. The Injector searches for Dependencies in the Providers using an Injection Token. Then, it creates an instance of the dependency and injects it into the consumer.

To understand the dependency injection in Angular, we can try setting up Dependency Injection from scratch, and the first step is to add a Provider.

A way of writing applications using only pure functions and immutable values. Click to explore about, Functional Programming

What is an Angular Dependency Injection Provider?

If we create a class and try to inject it into the Constructor of another class as a dependency, we get an error. This implies that our class is not linked to the Angular dependency injection system, and Angular needs to know how to create this dependency. So, for this, we need a provider.

 

The Angular dependency Injection Provider is a map between a token and a list of dependencies. It maintains the list of dependencies along with the injection token. For Angular to know how to create a dependency, it needs what is known as a provider factory function. It is simply an essential function that Angular can call to create a dependency. That provider factory function can be created implicitly by Angular using some simple conventions, which usually happens for most dependencies.

 

The dependencies are registered in the Provider metadata of the injector. We can understand this with an example. In the example, the service is registered with the injector of the AppComponent. The above example is the shorthand notation for the following syntax.

 

providers :[{ provide: ProductService, useClass: ProductService }]

The above syntax has two properties.

Provide

The first property is Provide, which holds the Token or DI Token. The Token can be a type, a string, or an instance of InjectionToken. The Injector uses the token to locate the Provider in the Providers array.

Provider

The second property is known as the Provider definition object. It shows Angular how to create the dependency instance. Angular creates the dependency instance in four different ways.

  • Creating a dependency from the existing service class (useClass).

  • Injecting a value, array, or object (useValue).

  • Using a factory function returns the service class or value (use factory).

  • I am returning the instance from an existing token (use existing).

We can also add the Services to the Providers array of the NgModule. This way, they are available to be used in all application components and services as they are added at the module level. But we can also write that function ourselves if needed.

Asking for Dependency in the Constructor

The Components, Directives, & Services (Consumers) declare the dependencies they need in their Constructor.

constructor(private productService:ProductService) {
}

 

The injector reads the dependencies via the Consumer's constructor. After the injector reads the dependencies, it looks for that dependency in the Provider. The Provider then provides an instance for the dependency and injector and injects it into the consumer.

How to write our Provider?

We can write our provider factory function to set up Angular dependency injection from scratch and better understand the framework. The Provider Factory function is just a simple function that inputs any dependencies that the consumer needs. It calls the Constructor of the consumer, passes all the needed dependencies, and returns the new CoursesService instance as the output.

 

But then there is a problem: how will the Angular dependency injection system know about this function, and how will it know it needs to call it to inject a particular dependency? So, there comes the role of Injection tokens.

We have to define the following things when we manually configure a provider:

  • Use factory: This contains a reference to the provider factory function that Angular calls whenever it needs to create dependencies and then injects them

  • Provide: This consists of the injection token linked to the dependency. The injection token helps Angular determine when a provider factory function should be called.

  • Dips: This is an array that contains any dependencies that the useFactory function needs to run, for example, an HTTP client in the case of a service that makes a call to the backend

Simplified Configuration of Providers: use class

There is another way to explicitly define a provider factory function instead of a provider factory function with the help of useFactory, which is the useClass property. We use the Class Provider useClass whenever we need to provide an instance of the provided class. The type passed to use class helps the injector create a new instance and then inject it. When using the use class property, Angular will know that the value that we are passing is a valid constructor function:

Galen Framework has its special language Galen Specs for describing the positioning and alignment of elements on a Web page. Click to explore about, Responsive Design Testing with Galen Framework

What is an Injection Token?

So how does Angular know what has to be injected, where, and which provider factory function needs to be called to create which dependency? The injection tokens provide this. An injection token identifies something we want to be injected and uniquely identifies a category of dependencies. If we try configuring it manually, This token injection object will identify our dependency in the dependency injection system. It is an object, and it's unique, unlike, for example, a string.

 

This token object helps Angular uniquely identify a set of dependencies. We usually declare the Provider in the Provider's metadata. This is what it looks like.

providers :[{ provide: ProductService, useClass: ProductService }]

 

The syntax consists of two properties: provided (provide: ProductService) and provider (use class: ProductService). The first property, Provide, has the DI Token that acts as a key. The Dependency Injection systems require this key to locate the Provider in the Providers array.

Creating an Injectable Service and Injecting services

Dependency Injection is wired into the Angular framework. It provides components with injectable services, i.e., services that can be injected into the component, giving the component access to that service class. So now, to understand and relate to all the topics covered so far, let's understand the Dependency Injection flow with an example by creating an injectable service and then injecting that service into a class.

Creating an Injectable Service

Let's consider a service that provides users with data. To generate a new UserService class, use the following Angular CLI command.

 

ng generate service users/user

 

To define a class as a service in Angular, we use the @Injectable() decorator, which provides the metadata and allows Angular to inject it into a component as a dependency. Similarly, we use the @Injectable() decorator to indicate that a component or other class (such as another service, a pipe, or an NgModule) has a dependency.

 

When a new instance of a component class is created, the dependencies needed by this component class are determined by looking at the constructor parameter types. For example, the Constructor of UsersListComponent needs UsersService.
constructor(private service: UsersService) { }

 

When a component depends on a service, Angular first checks if its injector consists of any existing instances. If the service requested does not exist yet, it is created by the injector using a registered provider and then added to the injector before service is returned to Angular.

 

When all requested services are returned, Angular calls the component's Constructor and those services as arguments.

Injecting Services

Now that we've created an injectable service, we can inject the service into a component's constructor () by supplying a constructor argument along with the dependency type. We can understand this by injecting our UsersService in the component as follows, in which the UsersService is specified in the UsersListComponent Constructor.


constructor(user service: UserService) { }

What is Angular Hierarchical Dependency Injection?

We notice that in Angular, we specify the providers for the dependencies at multiple places, such as:

  • At the level of a module

  • At the level of a component

  • At the level of a directive

We can do this because the Angular dependency system is hierarchical. Now, let's understand what it means.

 

Whenever we need a dependency somewhere, Angular tries to find a provider for that dependency in the list of dependencies of that component. If Angular cannot find a provider at the component level, it tries to find one in the parent component. Once found, it instantiates and uses it, but if not found, it searches it in the parent of the parent and so on until the application's root component is reached. If no provider is found in the entire process, we get the error message 'No provider found.'

 

The hierarchical dependency injection allows us to build our application more modularly. With the hierarchical structure of DI, we can isolate sections of the application and give them their private dependencies or have parent components that only share specific dependencies with their child components and not with the rest of the component tree, etc.

Java vs Kotlin
Our solutions cater to diverse industries, focusing on serving ever-changing marketing needs. Click here for our Custom AngularJS Development Services.

Conclusion

We can now state that the Angular Dependency Injection system is flexible, with many configuration options, and super easy to use. This Dependency Injection paradigm works through a hierarchy of injections. Injectors receive the instructions, and then they instantiate the requested dependency. So, the classes receive dependencies externally rather than creating them or knowing about them.

 

The Angular DI system is hierarchical, which means it contains two separate injection hierarchies (components and modules). This makes it easy to define in a very fine-grained way which dependencies are visible in which parts of the application and which dependencies are hidden.

Next Steps with Angular Dependency Injection

Talk to our experts about implementing compound AI system, How Industries and different departments use Agentic Workflows and Decision Intelligence to Become Decision Centric. Utilizes AI to automate and optimize IT support and operations, improving efficiency and responsiveness.

More Ways to Explore Us

Angular for React Developers: A Comprehensive Learning

arrow-checkmark

Creating Reusable Angular Components | In Depth Guide

arrow-checkmark

Angular Coding Style Guide

arrow-checkmark

 

Table of Contents

navdeep-singh-gill

Navdeep Singh Gill

Global CEO and Founder of XenonStack

Navdeep Singh Gill is serving as Chief Executive Officer and Product Architect at XenonStack. He holds expertise in building SaaS Platform for Decentralised Big Data management and Governance, AI Marketplace for Operationalising and Scaling. His incredible experience in AI Technologies and Big Data Engineering thrills him to write about different use cases and its approach to solutions.

Get the latest articles in your inbox

Subscribe Now