Tag Archives: Providers

Hierarchical Dependency Injection in Angular

DI (Dependency Injection) in Angular 2.0 is hierarchical in nature, for dependency injection to be able to create instances for you, you need to register providers for these classes (or other values) somewhere. and you can configure providers for DI at different levels

  • For the whole application when bootstrapping it. In this cases, all sub injectors (the component ones) will see this provider and share the instance associated with. When interacting, it will be the same instance
  • For a specific component and its sub components. Same as before but for à specific component. Other components won’t see this provider. If you redefine something defined above (when bootstrapping for example), this provider will be used instead. So you can override things. If a provider is registered in one of the child components a new (different) instance is provided for descendants of this component.
  • If a component requests an instance (by a constructor parameter), DI looks “upwards” the component tree (starting from leaf towards the root) and takes the first provider it finds. If an instance for this provider was already created previously, this instance is used, otherwise a new instance is created.

For e.g. In the bbelow sample we have hirerachy of components in this manner

App Component => Parent Component => Child Component => Grand Child component

Comp-Hirerarchy1

All the components share a Utility Service which looks some thing like this 

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

@Injectable()
export class UtilityService {
  public currentDateTime : Date;
  constructor() { 
    console.log("Inside Utility Service Constructor");
    this.currentDateTime = new Date();
  }

}

As you can see service is not doing any thing special it just has a date time variable which gets initialized when instance of that service is created.

These components are rendered dynamically based on button clicks in following sequence
Comp-Hirerarchy2

Click on Show hide it renders the Parent component, in this case parent component is using same instance as that of App Component, it is had not provided its own provider. So the date time which is displayed is same in app and parent component.

Comp-Hirerarchy3

Click on show hide of parent component it renders Child Component, not in this case it will display a new date time as we have specified provider of Utility service inside Child Component.

Comp-Hirerarchy4

import { Component, OnInit } from '@angular/core';
import { UtilityService } from './../services/utility.service';
@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css'],
  providers: [UtilityService]
})
export class ChildComponent implements OnInit {
  public currentDateTime : string;
  constructor(private utilService: UtilityService) {
    this.currentDateTime = this.utilService.currentDateTime.toISOString();
   }

  ngOnInit() {
  }
}

Now the grand child component is not defining it own provider, so it is using the same instance as that of its ancestor which in this case is child component. So the date time which is displayed in the child component and grand child component is same.

Providers are usually singleton (one instance) objects, that other objects have access to through dependency injection (DI).  Provider is Angular’s term for these reusable objects (dependencies).

Provider lookup – When a component or directive has a dependency (constructor parameter), DI starts looking on this components injector for providers, if it has one it requests the instance from this provider and injects it. If the injector doesn’t have a provider for the requested key (type) then the parent injector is visited, up to the root (bootstrap) until a provider is found and its instance can be injected. (if no provider is found DI throws an error).

We often declare providers in angular this way:

providers: [AnyService]

Which is short cut for representing this

[new Provider(AnyService, {useClass: AnyService})]

 

Complete source code can be found at Github