3d cartoon hands holding a phone

Unlock full course by purchasing a membership

Lesson 9

Understanding Dependency Injection in Angular

STANDARD

Understanding Dependency Injection in Angular

Dependency injection is another concept that is not unique to Angular, it is a general programming pattern. In the context of Angular, the idea is that instead of creating instances of classes ourselves, e.g:

export class AppComponent {
    myService = new MyService();
}

Angular will handle creating new instances of our classes, and provide them to us through dependency injection which looks like this:

export class AppComponent {
    constructor(private myService: MyService){}
}

or this:

export class AppComponent {
  private myService = inject(MyService);
}

Angular will use the MyService type here as an InjectionToken. This is how Angular knows we want an instance of MyService. The instance of MyService is assigned to myService and then we can use it. By using the private or public keyword, this will make myService available as a class member to the entire class, rather than just being available within the constructor.

Technically, the private keyword is only required for the inject syntax if you want the class member to specifically be private.

NOTE: Using the private keyword means it will only be available within the class. If you need it to also be available to the template for this class you can use the public keyword.

In both of the examples above, we now have an instance of MyService that is available on this.myService throughout the class.

Why Dependency Injection?

Why do this in Angular? Why not just create new instances ourselves? Some benefits are:

  1. It makes automated testing easier as we can easily provide fake versions of dependencies instead of real ones (automated testing is a bit more advanced and not something we actually cover in this course)
  2. It allows us to share instances of our objects more easily. This way we can have two separate components share the same single instance of a service, which means they will be able to share data, or we could create two separate instances of the service if we prefer.
  3. It makes creating instances much easier, as we don’t need to pass all of the dependencies that the service itself depends on.

That last one is a bit less clear, so let’s expand on that. Imagine that MyService also has two dependencies of its own that it needs injected:

export class MyService {
    constructor(http: HttpClient, someOtherService: SomeOtherService){}
}

To do its job, MyService also needs an instance of HttpClient and SomeOtherService. If we are using Angular’s dependency injection system then we can just do this to inject MyService somewhere else in our app:

export class AppComponent {
    constructor(private myService: MyService){}
}

But if we are not using dependency injection, then we need to pass all of the MyService dependencies manually like this:

export class AppComponent {
    myService = new MyService(new HttpClient(), new SomeOtherService())
}

Imagine doing this several times throughout your application, and then we need to update MyService to have a third dependency:

export class MyService {
    constructor(http: HttpClient, someOtherService: SomeOtherService, anotherService: AnotherService){}
}

Now we would need to go back and update every instance of MyService we are creating:

export class AppComponent {
    myService = new MyService(new HttpClient(), new SomeOtherService(), new AnotherService())
}

Perhaps you can see how this would become a massive pain.

Understanding Tokens and Providers

We have already seen how dependency injection works:

STANDARD
Key

Thanks for checking out the preview of this lesson!

You do not have the appropriate membership to view the full lesson. If you would like full access to this module you can view membership options (or log in if you are already have an appropriate membership).