|
|
|
@ -7,239 +7,369 @@
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
import {stringify} from '../facade/lang';
|
|
|
|
|
import {makeParamDecorator} from '../util/decorators';
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* A parameter metadata that specifies a dependency.
|
|
|
|
|
* Type of the Inject decorator / constructor function.
|
|
|
|
|
*
|
|
|
|
|
* ### Example ([live demo](http://plnkr.co/edit/6uHYJK?p=preview))
|
|
|
|
|
*
|
|
|
|
|
* ```typescript
|
|
|
|
|
* class Engine {}
|
|
|
|
|
*
|
|
|
|
|
* @Injectable()
|
|
|
|
|
* class Car {
|
|
|
|
|
* engine;
|
|
|
|
|
* constructor(@Inject("MyEngine") engine:Engine) {
|
|
|
|
|
* this.engine = engine;
|
|
|
|
|
* }
|
|
|
|
|
* }
|
|
|
|
|
*
|
|
|
|
|
* var injector = Injector.resolveAndCreate([
|
|
|
|
|
* {provide: "MyEngine", useClass: Engine},
|
|
|
|
|
* Car
|
|
|
|
|
* ]);
|
|
|
|
|
*
|
|
|
|
|
* expect(injector.get(Car).engine instanceof Engine).toBe(true);
|
|
|
|
|
* ```
|
|
|
|
|
*
|
|
|
|
|
* When `@Inject()` is not present, {@link Injector} will use the type annotation of the parameter.
|
|
|
|
|
*
|
|
|
|
|
* ### Example
|
|
|
|
|
*
|
|
|
|
|
* ```typescript
|
|
|
|
|
* class Engine {}
|
|
|
|
|
*
|
|
|
|
|
* @Injectable()
|
|
|
|
|
* class Car {
|
|
|
|
|
* constructor(public engine: Engine) {} //same as constructor(@Inject(Engine) engine:Engine)
|
|
|
|
|
* }
|
|
|
|
|
*
|
|
|
|
|
* var injector = Injector.resolveAndCreate([Engine, Car]);
|
|
|
|
|
* expect(injector.get(Car).engine instanceof Engine).toBe(true);
|
|
|
|
|
* ```
|
|
|
|
|
* @stable
|
|
|
|
|
*/
|
|
|
|
|
export class InjectMetadata {
|
|
|
|
|
constructor(public token: any) {}
|
|
|
|
|
toString(): string { return `@Inject(${stringify(this.token)})`; }
|
|
|
|
|
export interface InjectMetadataFactory {
|
|
|
|
|
/**
|
|
|
|
|
* A parameter metadata that specifies a dependency.
|
|
|
|
|
*
|
|
|
|
|
* ### Example ([live demo](http://plnkr.co/edit/6uHYJK?p=preview))
|
|
|
|
|
*
|
|
|
|
|
* ```typescript
|
|
|
|
|
* class Engine {}
|
|
|
|
|
*
|
|
|
|
|
* @Injectable()
|
|
|
|
|
* class Car {
|
|
|
|
|
* engine;
|
|
|
|
|
* constructor(@Inject("MyEngine") engine:Engine) {
|
|
|
|
|
* this.engine = engine;
|
|
|
|
|
* }
|
|
|
|
|
* }
|
|
|
|
|
*
|
|
|
|
|
* var injector = Injector.resolveAndCreate([
|
|
|
|
|
* {provide: "MyEngine", useClass: Engine},
|
|
|
|
|
* Car
|
|
|
|
|
* ]);
|
|
|
|
|
*
|
|
|
|
|
* expect(injector.get(Car).engine instanceof Engine).toBe(true);
|
|
|
|
|
* ```
|
|
|
|
|
*
|
|
|
|
|
* When `@Inject()` is not present, {@link Injector} will use the type annotation of the
|
|
|
|
|
* parameter.
|
|
|
|
|
*
|
|
|
|
|
* ### Example
|
|
|
|
|
*
|
|
|
|
|
* ```typescript
|
|
|
|
|
* class Engine {}
|
|
|
|
|
*
|
|
|
|
|
* @Injectable()
|
|
|
|
|
* class Car {
|
|
|
|
|
* constructor(public engine: Engine) {} //same as constructor(@Inject(Engine) engine:Engine)
|
|
|
|
|
* }
|
|
|
|
|
*
|
|
|
|
|
* var injector = Injector.resolveAndCreate([Engine, Car]);
|
|
|
|
|
* expect(injector.get(Car).engine instanceof Engine).toBe(true);
|
|
|
|
|
* ```
|
|
|
|
|
* @stable
|
|
|
|
|
*/
|
|
|
|
|
(token: any): any;
|
|
|
|
|
new (token: any): Inject;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* A parameter metadata that marks a dependency as optional. {@link Injector} provides `null` if
|
|
|
|
|
* the dependency is not found.
|
|
|
|
|
* Type of the Inject metadata.
|
|
|
|
|
*
|
|
|
|
|
* ### Example ([live demo](http://plnkr.co/edit/AsryOm?p=preview))
|
|
|
|
|
*
|
|
|
|
|
* ```typescript
|
|
|
|
|
* class Engine {}
|
|
|
|
|
*
|
|
|
|
|
* @Injectable()
|
|
|
|
|
* class Car {
|
|
|
|
|
* engine;
|
|
|
|
|
* constructor(@Optional() engine:Engine) {
|
|
|
|
|
* this.engine = engine;
|
|
|
|
|
* }
|
|
|
|
|
* }
|
|
|
|
|
*
|
|
|
|
|
* var injector = Injector.resolveAndCreate([Car]);
|
|
|
|
|
* expect(injector.get(Car).engine).toBeNull();
|
|
|
|
|
* ```
|
|
|
|
|
* @stable
|
|
|
|
|
*/
|
|
|
|
|
export class OptionalMetadata {
|
|
|
|
|
toString(): string { return `@Optional()`; }
|
|
|
|
|
export interface Inject { token: any; }
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Inject decorator and metadata.
|
|
|
|
|
*
|
|
|
|
|
* @stable
|
|
|
|
|
* @Annotation
|
|
|
|
|
*/
|
|
|
|
|
export const Inject: InjectMetadataFactory = makeParamDecorator([['token', undefined]]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Type of the Optional decorator / constructor function.
|
|
|
|
|
*
|
|
|
|
|
* @stable
|
|
|
|
|
*/
|
|
|
|
|
export interface OptionalMetadataFactory {
|
|
|
|
|
/**
|
|
|
|
|
* A parameter metadata that marks a dependency as optional. {@link Injector} provides `null` if
|
|
|
|
|
* the dependency is not found.
|
|
|
|
|
*
|
|
|
|
|
* ### Example ([live demo](http://plnkr.co/edit/AsryOm?p=preview))
|
|
|
|
|
*
|
|
|
|
|
* ```typescript
|
|
|
|
|
* class Engine {}
|
|
|
|
|
*
|
|
|
|
|
* @Injectable()
|
|
|
|
|
* class Car {
|
|
|
|
|
* engine;
|
|
|
|
|
* constructor(@Optional() engine:Engine) {
|
|
|
|
|
* this.engine = engine;
|
|
|
|
|
* }
|
|
|
|
|
* }
|
|
|
|
|
*
|
|
|
|
|
* var injector = Injector.resolveAndCreate([Car]);
|
|
|
|
|
* expect(injector.get(Car).engine).toBeNull();
|
|
|
|
|
* ```
|
|
|
|
|
* @stable
|
|
|
|
|
*/
|
|
|
|
|
(): any;
|
|
|
|
|
new (): Optional;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* `DependencyMetadata` is used by the framework to extend DI.
|
|
|
|
|
* This is internal to Angular and should not be used directly.
|
|
|
|
|
* Type of the Optional metadata.
|
|
|
|
|
*
|
|
|
|
|
* @stable
|
|
|
|
|
*/
|
|
|
|
|
export class DependencyMetadata {
|
|
|
|
|
get token(): any { return null; }
|
|
|
|
|
export interface Optional {}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Optional decorator and metadata.
|
|
|
|
|
*
|
|
|
|
|
* @stable
|
|
|
|
|
* @Annotation
|
|
|
|
|
*/
|
|
|
|
|
export const Optional: OptionalMetadataFactory = makeParamDecorator([]);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Type of the Injectable decorator / constructor function.
|
|
|
|
|
*
|
|
|
|
|
* @stable
|
|
|
|
|
*/
|
|
|
|
|
export interface InjectableMetadataFactory {
|
|
|
|
|
/**
|
|
|
|
|
* A marker metadata that marks a class as available to {@link Injector} for creation.
|
|
|
|
|
*
|
|
|
|
|
* ### Example ([live demo](http://plnkr.co/edit/Wk4DMQ?p=preview))
|
|
|
|
|
*
|
|
|
|
|
* ```typescript
|
|
|
|
|
* @Injectable()
|
|
|
|
|
* class UsefulService {}
|
|
|
|
|
*
|
|
|
|
|
* @Injectable()
|
|
|
|
|
* class NeedsService {
|
|
|
|
|
* constructor(public service:UsefulService) {}
|
|
|
|
|
* }
|
|
|
|
|
*
|
|
|
|
|
* var injector = Injector.resolveAndCreate([NeedsService, UsefulService]);
|
|
|
|
|
* expect(injector.get(NeedsService).service instanceof UsefulService).toBe(true);
|
|
|
|
|
* ```
|
|
|
|
|
* {@link Injector} will throw {@link NoAnnotationError} when trying to instantiate a class that
|
|
|
|
|
* does not have `@Injectable` marker, as shown in the example below.
|
|
|
|
|
*
|
|
|
|
|
* ```typescript
|
|
|
|
|
* class UsefulService {}
|
|
|
|
|
*
|
|
|
|
|
* class NeedsService {
|
|
|
|
|
* constructor(public service:UsefulService) {}
|
|
|
|
|
* }
|
|
|
|
|
*
|
|
|
|
|
* var injector = Injector.resolveAndCreate([NeedsService, UsefulService]);
|
|
|
|
|
* expect(() => injector.get(NeedsService)).toThrowError();
|
|
|
|
|
* ```
|
|
|
|
|
* @stable
|
|
|
|
|
*/
|
|
|
|
|
(): any;
|
|
|
|
|
new (): Injectable;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* A marker metadata that marks a class as available to {@link Injector} for creation.
|
|
|
|
|
* Type of the Injectable metadata.
|
|
|
|
|
*
|
|
|
|
|
* ### Example ([live demo](http://plnkr.co/edit/Wk4DMQ?p=preview))
|
|
|
|
|
*
|
|
|
|
|
* ```typescript
|
|
|
|
|
* @Injectable()
|
|
|
|
|
* class UsefulService {}
|
|
|
|
|
*
|
|
|
|
|
* @Injectable()
|
|
|
|
|
* class NeedsService {
|
|
|
|
|
* constructor(public service:UsefulService) {}
|
|
|
|
|
* }
|
|
|
|
|
*
|
|
|
|
|
* var injector = Injector.resolveAndCreate([NeedsService, UsefulService]);
|
|
|
|
|
* expect(injector.get(NeedsService).service instanceof UsefulService).toBe(true);
|
|
|
|
|
* ```
|
|
|
|
|
* {@link Injector} will throw {@link NoAnnotationError} when trying to instantiate a class that
|
|
|
|
|
* does not have `@Injectable` marker, as shown in the example below.
|
|
|
|
|
*
|
|
|
|
|
* ```typescript
|
|
|
|
|
* class UsefulService {}
|
|
|
|
|
*
|
|
|
|
|
* class NeedsService {
|
|
|
|
|
* constructor(public service:UsefulService) {}
|
|
|
|
|
* }
|
|
|
|
|
*
|
|
|
|
|
* var injector = Injector.resolveAndCreate([NeedsService, UsefulService]);
|
|
|
|
|
* expect(() => injector.get(NeedsService)).toThrowError();
|
|
|
|
|
* ```
|
|
|
|
|
* @stable
|
|
|
|
|
*/
|
|
|
|
|
export class InjectableMetadata {
|
|
|
|
|
constructor() {}
|
|
|
|
|
export interface Injectable {}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Injectable decorator and metadata.
|
|
|
|
|
*
|
|
|
|
|
* @stable
|
|
|
|
|
* @Annotation
|
|
|
|
|
*/
|
|
|
|
|
export const Injectable: InjectableMetadataFactory = makeParamDecorator([]);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Type of the Self decorator / constructor function.
|
|
|
|
|
*
|
|
|
|
|
* @stable
|
|
|
|
|
*/
|
|
|
|
|
export interface SelfMetadataFactory {
|
|
|
|
|
/**
|
|
|
|
|
* Specifies that an {@link Injector} should retrieve a dependency only from itself.
|
|
|
|
|
*
|
|
|
|
|
* ### Example ([live demo](http://plnkr.co/edit/NeagAg?p=preview))
|
|
|
|
|
*
|
|
|
|
|
* ```typescript
|
|
|
|
|
* class Dependency {
|
|
|
|
|
* }
|
|
|
|
|
*
|
|
|
|
|
* @Injectable()
|
|
|
|
|
* class NeedsDependency {
|
|
|
|
|
* dependency;
|
|
|
|
|
* constructor(@Self() dependency:Dependency) {
|
|
|
|
|
* this.dependency = dependency;
|
|
|
|
|
* }
|
|
|
|
|
* }
|
|
|
|
|
*
|
|
|
|
|
* var inj = Injector.resolveAndCreate([Dependency, NeedsDependency]);
|
|
|
|
|
* var nd = inj.get(NeedsDependency);
|
|
|
|
|
*
|
|
|
|
|
* expect(nd.dependency instanceof Dependency).toBe(true);
|
|
|
|
|
*
|
|
|
|
|
* var inj = Injector.resolveAndCreate([Dependency]);
|
|
|
|
|
* var child = inj.resolveAndCreateChild([NeedsDependency]);
|
|
|
|
|
* expect(() => child.get(NeedsDependency)).toThrowError();
|
|
|
|
|
* ```
|
|
|
|
|
* @stable
|
|
|
|
|
*/
|
|
|
|
|
(): any;
|
|
|
|
|
new (): Self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Specifies that an {@link Injector} should retrieve a dependency only from itself.
|
|
|
|
|
* Type of the Self metadata.
|
|
|
|
|
*
|
|
|
|
|
* ### Example ([live demo](http://plnkr.co/edit/NeagAg?p=preview))
|
|
|
|
|
*
|
|
|
|
|
* ```typescript
|
|
|
|
|
* class Dependency {
|
|
|
|
|
* }
|
|
|
|
|
*
|
|
|
|
|
* @Injectable()
|
|
|
|
|
* class NeedsDependency {
|
|
|
|
|
* dependency;
|
|
|
|
|
* constructor(@Self() dependency:Dependency) {
|
|
|
|
|
* this.dependency = dependency;
|
|
|
|
|
* }
|
|
|
|
|
* }
|
|
|
|
|
*
|
|
|
|
|
* var inj = Injector.resolveAndCreate([Dependency, NeedsDependency]);
|
|
|
|
|
* var nd = inj.get(NeedsDependency);
|
|
|
|
|
*
|
|
|
|
|
* expect(nd.dependency instanceof Dependency).toBe(true);
|
|
|
|
|
*
|
|
|
|
|
* var inj = Injector.resolveAndCreate([Dependency]);
|
|
|
|
|
* var child = inj.resolveAndCreateChild([NeedsDependency]);
|
|
|
|
|
* expect(() => child.get(NeedsDependency)).toThrowError();
|
|
|
|
|
* ```
|
|
|
|
|
* @stable
|
|
|
|
|
*/
|
|
|
|
|
export class SelfMetadata {
|
|
|
|
|
toString(): string { return `@Self()`; }
|
|
|
|
|
export interface Self {}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Self decorator and metadata.
|
|
|
|
|
*
|
|
|
|
|
* @stable
|
|
|
|
|
* @Annotation
|
|
|
|
|
*/
|
|
|
|
|
export const Self: SelfMetadataFactory = makeParamDecorator([]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Type of the SkipSelf decorator / constructor function.
|
|
|
|
|
*
|
|
|
|
|
* @stable
|
|
|
|
|
*/
|
|
|
|
|
export interface SkipSelfMetadataFactory {
|
|
|
|
|
/**
|
|
|
|
|
* Specifies that the dependency resolution should start from the parent injector.
|
|
|
|
|
*
|
|
|
|
|
* ### Example ([live demo](http://plnkr.co/edit/Wchdzb?p=preview))
|
|
|
|
|
*
|
|
|
|
|
* ```typescript
|
|
|
|
|
* class Dependency {
|
|
|
|
|
* }
|
|
|
|
|
*
|
|
|
|
|
* @Injectable()
|
|
|
|
|
* class NeedsDependency {
|
|
|
|
|
* dependency;
|
|
|
|
|
* constructor(@SkipSelf() dependency:Dependency) {
|
|
|
|
|
* this.dependency = dependency;
|
|
|
|
|
* }
|
|
|
|
|
* }
|
|
|
|
|
*
|
|
|
|
|
* var parent = Injector.resolveAndCreate([Dependency]);
|
|
|
|
|
* var child = parent.resolveAndCreateChild([NeedsDependency]);
|
|
|
|
|
* expect(child.get(NeedsDependency).dependency instanceof Depedency).toBe(true);
|
|
|
|
|
*
|
|
|
|
|
* var inj = Injector.resolveAndCreate([Dependency, NeedsDependency]);
|
|
|
|
|
* expect(() => inj.get(NeedsDependency)).toThrowError();
|
|
|
|
|
* ```
|
|
|
|
|
* @stable
|
|
|
|
|
*/
|
|
|
|
|
(): any;
|
|
|
|
|
new (): SkipSelf;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Specifies that the dependency resolution should start from the parent injector.
|
|
|
|
|
* Type of the SkipSelf metadata.
|
|
|
|
|
*
|
|
|
|
|
* ### Example ([live demo](http://plnkr.co/edit/Wchdzb?p=preview))
|
|
|
|
|
*
|
|
|
|
|
* ```typescript
|
|
|
|
|
* class Dependency {
|
|
|
|
|
* }
|
|
|
|
|
*
|
|
|
|
|
* @Injectable()
|
|
|
|
|
* class NeedsDependency {
|
|
|
|
|
* dependency;
|
|
|
|
|
* constructor(@SkipSelf() dependency:Dependency) {
|
|
|
|
|
* this.dependency = dependency;
|
|
|
|
|
* }
|
|
|
|
|
* }
|
|
|
|
|
*
|
|
|
|
|
* var parent = Injector.resolveAndCreate([Dependency]);
|
|
|
|
|
* var child = parent.resolveAndCreateChild([NeedsDependency]);
|
|
|
|
|
* expect(child.get(NeedsDependency).dependency instanceof Depedency).toBe(true);
|
|
|
|
|
*
|
|
|
|
|
* var inj = Injector.resolveAndCreate([Dependency, NeedsDependency]);
|
|
|
|
|
* expect(() => inj.get(NeedsDependency)).toThrowError();
|
|
|
|
|
* ```
|
|
|
|
|
* @stable
|
|
|
|
|
*/
|
|
|
|
|
export class SkipSelfMetadata {
|
|
|
|
|
toString(): string { return `@SkipSelf()`; }
|
|
|
|
|
export interface SkipSelf {}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* SkipSelf decorator and metadata.
|
|
|
|
|
*
|
|
|
|
|
* @stable
|
|
|
|
|
* @Annotation
|
|
|
|
|
*/
|
|
|
|
|
export const SkipSelf: SkipSelfMetadataFactory = makeParamDecorator([]);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Type of the Host decorator / constructor function.
|
|
|
|
|
*
|
|
|
|
|
* @stable
|
|
|
|
|
*/
|
|
|
|
|
export interface HostMetadataFactory {
|
|
|
|
|
/**
|
|
|
|
|
* Specifies that an injector should retrieve a dependency from any injector until reaching the
|
|
|
|
|
* closest host.
|
|
|
|
|
*
|
|
|
|
|
* In Angular, a component element is automatically declared as a host for all the injectors in
|
|
|
|
|
* its view.
|
|
|
|
|
*
|
|
|
|
|
* ### Example ([live demo](http://plnkr.co/edit/GX79pV?p=preview))
|
|
|
|
|
*
|
|
|
|
|
* In the following example `App` contains `ParentCmp`, which contains `ChildDirective`.
|
|
|
|
|
* So `ParentCmp` is the host of `ChildDirective`.
|
|
|
|
|
*
|
|
|
|
|
* `ChildDirective` depends on two services: `HostService` and `OtherService`.
|
|
|
|
|
* `HostService` is defined at `ParentCmp`, and `OtherService` is defined at `App`.
|
|
|
|
|
*
|
|
|
|
|
*```typescript
|
|
|
|
|
* class OtherService {}
|
|
|
|
|
* class HostService {}
|
|
|
|
|
*
|
|
|
|
|
* @Directive({
|
|
|
|
|
* selector: 'child-directive'
|
|
|
|
|
* })
|
|
|
|
|
* class ChildDirective {
|
|
|
|
|
* constructor(@Optional() @Host() os:OtherService, @Optional() @Host() hs:HostService){
|
|
|
|
|
* console.log("os is null", os);
|
|
|
|
|
* console.log("hs is NOT null", hs);
|
|
|
|
|
* }
|
|
|
|
|
* }
|
|
|
|
|
*
|
|
|
|
|
* @Component({
|
|
|
|
|
* selector: 'parent-cmp',
|
|
|
|
|
* providers: [HostService],
|
|
|
|
|
* template: `
|
|
|
|
|
* Dir: <child-directive></child-directive>
|
|
|
|
|
* `,
|
|
|
|
|
* directives: [ChildDirective]
|
|
|
|
|
* })
|
|
|
|
|
* class ParentCmp {
|
|
|
|
|
* }
|
|
|
|
|
*
|
|
|
|
|
* @Component({
|
|
|
|
|
* selector: 'app',
|
|
|
|
|
* providers: [OtherService],
|
|
|
|
|
* template: `
|
|
|
|
|
* Parent: <parent-cmp></parent-cmp>
|
|
|
|
|
* `,
|
|
|
|
|
* directives: [ParentCmp]
|
|
|
|
|
* })
|
|
|
|
|
* class App {
|
|
|
|
|
* }
|
|
|
|
|
*```
|
|
|
|
|
* @stable
|
|
|
|
|
*/
|
|
|
|
|
(): any;
|
|
|
|
|
new (): Host;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Specifies that an injector should retrieve a dependency from any injector until reaching the
|
|
|
|
|
* closest host.
|
|
|
|
|
* Type of the Host metadata.
|
|
|
|
|
*
|
|
|
|
|
* In Angular, a component element is automatically declared as a host for all the injectors in
|
|
|
|
|
* its view.
|
|
|
|
|
*
|
|
|
|
|
* ### Example ([live demo](http://plnkr.co/edit/GX79pV?p=preview))
|
|
|
|
|
*
|
|
|
|
|
* In the following example `App` contains `ParentCmp`, which contains `ChildDirective`.
|
|
|
|
|
* So `ParentCmp` is the host of `ChildDirective`.
|
|
|
|
|
*
|
|
|
|
|
* `ChildDirective` depends on two services: `HostService` and `OtherService`.
|
|
|
|
|
* `HostService` is defined at `ParentCmp`, and `OtherService` is defined at `App`.
|
|
|
|
|
*
|
|
|
|
|
*```typescript
|
|
|
|
|
* class OtherService {}
|
|
|
|
|
* class HostService {}
|
|
|
|
|
*
|
|
|
|
|
* @Directive({
|
|
|
|
|
* selector: 'child-directive'
|
|
|
|
|
* })
|
|
|
|
|
* class ChildDirective {
|
|
|
|
|
* constructor(@Optional() @Host() os:OtherService, @Optional() @Host() hs:HostService){
|
|
|
|
|
* console.log("os is null", os);
|
|
|
|
|
* console.log("hs is NOT null", hs);
|
|
|
|
|
* }
|
|
|
|
|
* }
|
|
|
|
|
*
|
|
|
|
|
* @Component({
|
|
|
|
|
* selector: 'parent-cmp',
|
|
|
|
|
* providers: [HostService],
|
|
|
|
|
* template: `
|
|
|
|
|
* Dir: <child-directive></child-directive>
|
|
|
|
|
* `,
|
|
|
|
|
* directives: [ChildDirective]
|
|
|
|
|
* })
|
|
|
|
|
* class ParentCmp {
|
|
|
|
|
* }
|
|
|
|
|
*
|
|
|
|
|
* @Component({
|
|
|
|
|
* selector: 'app',
|
|
|
|
|
* providers: [OtherService],
|
|
|
|
|
* template: `
|
|
|
|
|
* Parent: <parent-cmp></parent-cmp>
|
|
|
|
|
* `,
|
|
|
|
|
* directives: [ParentCmp]
|
|
|
|
|
* })
|
|
|
|
|
* class App {
|
|
|
|
|
* }
|
|
|
|
|
*```
|
|
|
|
|
* @stable
|
|
|
|
|
*/
|
|
|
|
|
export class HostMetadata {
|
|
|
|
|
toString(): string { return `@Host()`; }
|
|
|
|
|
}
|
|
|
|
|
export interface Host {}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Host decorator and metadata.
|
|
|
|
|
*
|
|
|
|
|
* @stable
|
|
|
|
|
* @Annotation
|
|
|
|
|
*/
|
|
|
|
|
export const Host: HostMetadataFactory = makeParamDecorator([]);
|
|
|
|
|
|
|
|
|
|
// TODO(tbosch): remove this
|
|
|
|
|
export {
|
|
|
|
|
Host as HostMetadata,
|
|
|
|
|
Inject as InjectMetadata,
|
|
|
|
|
Injectable as InjectableMetadata,
|
|
|
|
|
Optional as OptionalMetadata,
|
|
|
|
|
Self as SelfMetadata,
|
|
|
|
|
SkipSelf as SkipSelfMetadata
|
|
|
|
|
};
|
|
|
|
|