Angular 2 Dependency Injection

30 / Jul / 2016 by Kavita Bora 0 comments

In this blog, we will go through the new dependency injection system of Angular 2. As we know DI is the heart of AngularJS. In Angular 1 we can inject dependency at multiple places in different ways such as:

  • in the directive definition by name   eg.

    [js]app.directive(‘questionTemplate’, [‘$http’, ‘Flash’, function($http, Flash) {}[/js]

  • in the controller function by name, etc. eg.

    [js]app.controller(‘myController’,[“$scope”,function($scope){}])[/js]

In Angular 2 there is only one way of injecting DI i.e Constructor injection by type,

[js]
constructor(dateUtil: DateUtil){
this.dateUtil = dateUtil
}

class DateUtil{
date:Date

constructor(date: string) {
this.date = new Date(string);
}

getDate() {
return this.date;
}
}[/js]

In the above example, it tells the constructor that class depends on “DateUtil” which in our case is a  utility wrapper for dealing with dates.Let’s start with  the concept of DI in Angular 2. The DI system in Angular 2 basically consists of three important aspects:

Injector:
The injector object provides us a mechanism by which the desired dependency is instantiated.To 
create an instance ,injector looks for a provider.

Provider:
A Provider is a medium by which we register our dependency that need to be inject. As with all DI frameworks, we have to inform them about the dependencies that we want to inject “somewhere”. The way we do this in Angular 2.0 is by specifying “providers” . This can be done in 2 ways

  • Registering the provider at the app level creates the injected dependency as a singleton  for the entire application eg.

    [js]bootstrap(App, [NameService]);[/js]

  • Providers at the component level result in new instances at the component level eg.

    [js]@Component({providers: [NameService]})[/js]

This is the difference in Angular 1 DI where we have only singleton dependency for the whole application.

Dependency
The dependency that we are injecting in a constructor is an object of the class that we want to use eg.   dateUtil:DateUtil 

Let’s suppose we have a class car which depends on Engine and Tire dependency

[js]
class Car{
constructor ( engine, tires ) {
this.engine = engine;
this.tires = tires;
}
}[/js]

Here’s how we can use Angular 2’s DI to get an instance of Car:

[js]
import { ReflectiveInjector } from ‘@angular/core’;

var injector = ReflectiveInjector.resolveAndCreate([ Car, Engine, Tires ]);
var car = injector.get(Car);
[/js]

How the injector works:

ReflectiveInjector is an injector implementation that gives resolveAndCreate() factory function that creates an injector object and takes a list of providers. How does injector know which dependencies need to be created in order to instantiate a car? In order to specify this, we simply use these objects in the Car constructor(engine, tires)  but we do not mention any dependencies about these classes yet.

[js]
import { Inject } from ‘angular2/core’;

class Car{
constructor ( @Inject(Engine) engine, @Inject(Tires tire{…})
}
[/js]

We import  Inject from the framework.The Inject decorator  attaches metadata to our Car class, which is used by the DI system later. So basically what we’re doing here, is that we tell the DI that the first constructor parameter should be an instance of type Engine, the second of type Tires.So we can rewrite our code in typescript-

[js]
class Car {
constructor ( engine: Engine, tires: Tires ) {

}
}
[/js]

How a provider works:

Still, injector does not know about the classes?.i.e we just provide a token of dependency but nothing about their classes like Engine, Tires.This is where the providers come into the picture.Let’s have a look how it goes-

[js]
import { provide } from ‘angular2/core’;

var injector = RelfectiveInjector.resolveAndCreate([
provide(Car, { useClass: Car }),
provide(Engine, { useClass:Engine }),
provide(Tires, { useClass:Tires })
]);[/js]

We have a function provide() that maps a token to a configuration object.We provide an instance of type Car via the class Car, type Engine via the class Engine and so on and so forth.So with the providers –

  1. We let the injector know which dependencies are used across the application i.e at the component level or app level as we talked earlier in above.
  2. We also configure how objects of these dependencies are created i.e which implementation used with the object.For example-

[js]
provide(Engine, {
useClass: OtherEngine
})
[/js]

We will use this syntax where we need to use a dependency with a different implementation.This is the powerful feature, about which we already talked in above i.e use same type dependency with different implementations.How it works in Angular 2-

Let’s take a look at a complete example, creating a simple Angular 2 component – which uses DI to inject dependencies:

[js]
@Component({
selector: ‘app’,
template: ‘<h1>Hello !</h1>’
})

class App {
constructor (@Inject(NameService) NameService){
this.name = NameService.getName();
}
}

class NameService {
constructor () {
this.name = ‘Pascal’;
}
getName () {
return this.name;
}
}

bootstrap(App, [NameService]);[/js]

bootstrap() takes care of creating a root injector for our application when it’s bootstrapped. It takes a list of providers as the second argument which will be passed straight to the injector when it is created.So I  hope you got the concept behind DI in Angular 2 & its working.

Read Further on AngularJS Series

FOUND THIS USEFUL? SHARE IT

Leave a Reply

Your email address will not be published. Required fields are marked *