Angular 2.0 Dependency injection

35
AngularJS 2.0 Dependency Injection Eyal Vard Site: http://ng-course.o Blog: eyalVardi.wordpress.

Transcript of Angular 2.0 Dependency injection

Page 1: Angular 2.0 Dependency injection

AngularJS 2.0 Dependency Injection

Eyal Vardi

Site: http://ng-course.org

Blog: eyalVardi.wordpress.com

Page 2: Angular 2.0 Dependency injection

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

Page 3: Angular 2.0 Dependency injection

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.

Page 4: Angular 2.0 Dependency injection

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);

Page 5: Angular 2.0 Dependency injection

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

Page 6: Angular 2.0 Dependency injection

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);}

Page 7: Angular 2.0 Dependency injection

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.

Page 8: Angular 2.0 Dependency injection

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){ //... }}

Page 9: Angular 2.0 Dependency injection

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);

Page 10: Angular 2.0 Dependency injection

Configuring the Injector with NgModulesApplication Injector

AppModule

UsersModule BrowserModule HttpModule

Sub InjectorSub InjectorContactsModule

ContactsModule

Page 11: Angular 2.0 Dependency injection

Providers

Page 12: Angular 2.0 Dependency injection

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

Page 13: Angular 2.0 Dependency injection

The Provider

[ServiceA]

{ provide : ServiceA , useClass : ServiceA }==

 token  "recipe" for creating

Page 14: Angular 2.0 Dependency injection

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] })]);

Page 15: Angular 2.0 Dependency injection

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

Page 16: Angular 2.0 Dependency injection

Provider Type useClass? : Type,

useValue? : any,

useExisting?: any,

useFactory? : Function,

deps? : Object[],

multi? : boolean

Page 17: Angular 2.0 Dependency injection

Hierarchical Injection

Page 18: Angular 2.0 Dependency injection

Injection ResolutionPlatform Injectors

Component Injectors

AppElement

Element

1

2

4

Application Injectors3

Page 19: Angular 2.0 Dependency injection

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

Page 20: Angular 2.0 Dependency injection

Component Injectors

<component my-

directive>

<sub-comp/>

<sub-comp/>

</component>

Component Injector

<component my-

directive>

<sub-comp/>

<sub-comp/>

</component>

Page 21: Angular 2.0 Dependency injection

Component Injector

Component Directive

TemplateContent

*

* *

viewProviders

directivespipes

Providers@ContentChild@ContentChildren

@ViewChild@ViewChildre

n

DOM Element

Page 22: Angular 2.0 Dependency injection

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

Page 23: Angular 2.0 Dependency injection

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

Page 24: Angular 2.0 Dependency injection

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

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

Page 25: Angular 2.0 Dependency injection

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

Page 26: Angular 2.0 Dependency injection

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

Page 27: Angular 2.0 Dependency injection

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>)

Page 28: Angular 2.0 Dependency injection

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.

Page 29: Angular 2.0 Dependency injection

Opaque Token

Page 30: Angular 2.0 Dependency injection

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"})]);

Page 31: Angular 2.0 Dependency injection

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}]

Page 32: Angular 2.0 Dependency injection

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.

Page 33: Angular 2.0 Dependency injection

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' } ]})

Page 34: Angular 2.0 Dependency injection

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

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

Page 35: Angular 2.0 Dependency injection

Thankseyalvardi.wordpress.com

Eyal Vardi

Site: http://ng-course.org

Blog: eyalVardi.wordpress.com