angular 2.0 dependency injection

Post on 16-Apr-2017

2.995 Views

Category:

Software

1 Downloads

Preview:

Click to see full reader

TRANSCRIPT

AngularJS 2.0 Dependency Injection

Eyal Vardi

Site: http://ng-course.org

Blog: eyalVardi.wordpress.com

Agenda Dependency Injection Overview Injector Class Provider Options Injectors Tree Injection Resolution Opaque Token

Dependency Injection Overview Angular ships with its own Dependency

Injection framework. This framework can also be used as a

standalone module by other applications and frameworks.

Injector Overview A dependency injection container used for

instantiating objects and resolving dependencies.

An Injector is a replacement for a new operator, which can automatically resolve the constructor dependencies.import {Injectable,Injector} from '@angular/core';

@Injectable() class Engine {}

@Injectable() class Car { constructor(public engine:Engine) {} }

var injector = Injector.resolveAndCreate([Car, Engine]);

var car = injector.get(Car);

Core Abstractions An injector is created from a set of providers. An injector resolves dependencies and creates

objects. A provider maps a token, such as a string or

class, to a factory function and a list of dependencies. Injector

FactoryFn

Token Flags

Token

Provider*

Dependency*

ProtoInjectorinjectable

s

ProtoInjector Store meta information about

injectables, and injectables themselves are stored in Injector.

Injector.resolveAndCreate creates both a ProtoInjector and an Injector.function createComponentInjector(parent, proto) { return new Injector(proto, parent);}

Injector Class Methods & Properties that return

Injector: parent resolveAndCreate resolveAndCreateChild createChildFromResolved

Methods that return resolved object: get getOptional * resolveAndInstantiate * instantiateResolved

* The created object does not get cached by the injector.

A

Child Injector

Parent InjectorA,B,C

Child Injector

A,B

Child Injector

A

var p = Injector.resolveAndCreate([A,B,C])

var c1 = p.resolveAndCreateChild([A,B])

var c2 = c1.resolveAndCreateChild([A])

c2.get(A) =>

B C@Injectable()class A{ constructor(b:B,c:C){ //... }}

Configuring the Injector We don't have to create the injector.  We can configure the injector at the

same time that we bootstrap. @NgModule({ declarations:[AppComponent, ... ], providers :[UserProxy], bootstrap :[AppComponent], imports :[...], exports :[]})export class AppModule{}

platformBrowserDynamic() .bootstrapModule(AppModule);

Configuring the Injector with NgModulesApplication Injector

AppModule

UsersModule BrowserModule HttpModule

Sub InjectorSub InjectorContactsModule

ContactsModule

Providers

Injector Providers "Providers" create the instances of the

things that we ask the injector to inject.  A class is a natural provider - it's meant

to be created.

providers : [ ServiceA, ServiceB, … ]

 providers

The Provider

[ServiceA]

{ provide : ServiceA , useClass : ServiceA }==

 token  "recipe" for creating

Factory Providers@Injectable()function logger(msg){ console.log(msg);}

bootstrap(App,[ provide(logger,{useValue: logger}), provide(Service,{ useFactory : (logger)=>{ return { load(){ logger('load'); } } }, deps:[logger] })]);

String tokens The token can be:

String Class type OpaqueToken

providers:[ ServiceA, { provide: 'app.config', useValue: {name:'ev'} }]

constructor( service:ServiceA, @Inject('app.config') config)

 Class token

String token

Provider Type useClass? : Type,

useValue? : any,

useExisting?: any,

useFactory? : Function,

deps? : Object[],

multi? : boolean

Hierarchical Injection

Injection ResolutionPlatform Injectors

Component Injectors

AppElement

Element

1

2

4

Application Injectors3

ComponentMetadata

Component Metadata Names:

selector? : string exportAs? : string

Binding: inputs? : string[] outputs? : string[] host? : {[key: string]: string} changeDetection?: ChangeDetectionStrategy

View: templateUrl? : string template? : string styleUrls? : string[] styles? : string[] encapsulation?:

ViewEncapsulation

Injector: providers? : any[] viewProviders? : any[] queries? : {[key: string]: any} Directive

Metadata

Component Injectors

<component my-

directive>

<sub-comp/>

<sub-comp/>

</component>

Component Injector

<component my-

directive>

<sub-comp/>

<sub-comp/>

</component>

Component Injector

Component Directive

TemplateContent

*

* *

viewProviders

directivespipes

Providers@ContentChild@ContentChildren

@ViewChild@ViewChildre

n

DOM Element

Component InjectorsComponent Injector

<component>

<sub-comp/>

<sub-comp/>

<sub-comp/>

</component>

providers @host

@ContentChild@ContentChildren

@Component({ selector :'component', template:`...`, providers :[], viewProviders:[]})class Component{}

viewProviders | Directives<div my-direc> Hello World… <ng-content/></div>

@ViewChild@ViewChildren

Template

Host & Visibility Public - Is only visible to regular child injectors. Private - Is only visible to host child injectors. PublicAndPrivate

is visible to both host and regular child injectors.

viewProviders

Component (@host)Injector

Providers

Template

Constructor Injection Options directive : DirectiveType @Host() directive : DirectiveType

To inject element-specific special objects: element : ElementRef viewContainer : ViewContainerRef changeDetector : ChangeDetectorRef template : TemplateRef

Constructor Injection Options@Component({...})export class MyComponent { constructor( element : ElementRef ,viewContainer : ViewContainerRef ,changeDetector: ChangeDetectorRef ,template : TemplateRef , render : Renderer ){...}}

Compiletime vs. Runtimeimport {Component} from "@angular/core";import {Type1,Type2,Type3} from "eyalVardi";import {Pipe1,Directive1} from "eyalVardi";import {Component2} from "eyalVardi";import {Service1} from "eyalVardi";

@Component({ providers :[Type1,Type2], viewProviders:[Type3]})export class MyComponent { constructor( element : ElementRef ){}}

Can solve by theimport?

Must solve in runtime

by the Injector

Sample<div dependency="1"> <div dependency="2"> <div dependency="3" my-directive> <div dependency="4"> <div dependency="5"></div> </div> <div dependency="6"></div> </div> </div></div>

Dependency

MyDirective Constructor

3 constructor(dependency: Dependency)2 constructor(@Host() dependency: Dependency)

4 , 6 constructor(@Query(Dependency) dependencies:QueryList<Dependency>)

4 , 5 , 6 constructor(@Query(Dependency, {descendants: true}) dependencies:QueryList<Dependency>)

More Options constructor(@Self()

dependency:Dependency) Specifies that an Injector should retrieve a

dependency only from itself. (3)

constructor(@SkipSelf() dependency:Dependency) Specifies that the dependency resolution should

start from the parent injector. (2)

constructor(@Optional() engine:Engine) Injector provides null if the dependency is not

found.

Opaque Token

OpaqueToken Class Creates a token that can be used in a DI

Provider.

Using an OpaqueToken is preferable to using strings as tokens.

var t = new OpaqueToken("value");var injector = Injector.resolveAndCreate([ provide(t, {useValue: "providedValue"})]);

OpaqueToken Initialize Events PLATFORM_INITIALIZER

A function that will be executed when a platform is initialized.

APP_INITIALIZERA function that will be executed when an application is initialized.

providers:[ provide{ APP_INITIALIZER ,useValue: appInit , multi: true}, provide{ PLATFORM_INITIALIZER,useValue: platformInit, multi: true}]

APP_ID A DI Token representing a unique string

id assigned to the application by Angular. Used primarily for prefixing application

attributes and CSS styles when ViewEncapsulation is being used.

APP_BASE_HREF Token represents the base href to be

used with the PathLocationStrategy.@NgModule({providers: [ ROUTER_PROVIDERS, PathLocationStrategy, { provide: APP_BASE_HREF, useValue: '/my/app' } ]})

Resources Angular.io site (Developer guides - forms) Ng-Book 2 (

The Ultimate Guide to Forms in Angular 2 ) GitHub (Angular code source)

Thankseyalvardi.wordpress.com

Eyal Vardi

Site: http://ng-course.org

Blog: eyalVardi.wordpress.com

top related