Angular 2.0 Dependency injection
-
Upload
eyal-vardi -
Category
Software
-
view
2.982 -
download
1
Transcript of Angular 2.0 Dependency injection
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