diff --git a/modules/@angular/compiler-cli/src/static_reflector.ts b/modules/@angular/compiler-cli/src/static_reflector.ts index 1150b1dbc1..6db04a24a4 100644 --- a/modules/@angular/compiler-cli/src/static_reflector.ts +++ b/modules/@angular/compiler-cli/src/static_reflector.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {AttributeMetadata, ComponentMetadata, ContentChildMetadata, ContentChildrenMetadata, DirectiveMetadata, HostBindingMetadata, HostListenerMetadata, HostMetadata, InjectMetadata, InjectableMetadata, InputMetadata, NgModuleMetadata, OptionalMetadata, OutputMetadata, PipeMetadata, QueryMetadata, SelfMetadata, SkipSelfMetadata, ViewChildMetadata, ViewChildrenMetadata, ViewQueryMetadata, animate, group, keyframes, sequence, state, style, transition, trigger} from '@angular/core'; +import {AttributeMetadata, ComponentMetadata, ContentChildMetadata, ContentChildrenMetadata, DirectiveMetadata, HostBindingMetadata, HostListenerMetadata, HostMetadata, InjectMetadata, InjectableMetadata, InputMetadata, NgModuleMetadata, OptionalMetadata, OutputMetadata, PipeMetadata, QueryMetadata, SelfMetadata, SkipSelfMetadata, ViewChildMetadata, ViewChildrenMetadata, animate, group, keyframes, sequence, state, style, transition, trigger} from '@angular/core'; import {ReflectorReader} from './private_import_core'; @@ -169,16 +169,11 @@ export class StaticReflector implements ReflectorReader { } private registerDecoratorOrConstructor(type: StaticSymbol, ctor: any): void { - this.conversionMap.set(type, (context: StaticSymbol, args: any[]) => { - var metadata = Object.create(ctor.prototype); - ctor.apply(metadata, args); - return metadata; - }); + this.conversionMap.set(type, (context: StaticSymbol, args: any[]) => new ctor(...args)); } private registerFunction(type: StaticSymbol, fn: any): void { - this.conversionMap.set( - type, (context: StaticSymbol, args: any[]) => { return fn.apply(undefined, args); }); + this.conversionMap.set(type, (context: StaticSymbol, args: any[]) => fn.apply(undefined, args)); } private initializeConversionMap(): void { diff --git a/modules/@angular/compiler-cli/test/static_reflector_spec.ts b/modules/@angular/compiler-cli/test/static_reflector_spec.ts index a1d0fa0f7b..213054fdd2 100644 --- a/modules/@angular/compiler-cli/test/static_reflector_spec.ts +++ b/modules/@angular/compiler-cli/test/static_reflector_spec.ts @@ -431,7 +431,7 @@ describe('StaticReflector', () => { const annotations = reflector.annotations( host.getStaticSymbol('/tmp/src/static-method-ref.ts', 'MethodReference')); expect(annotations.length).toBe(1); - expect(annotations[0]._providers[0].useValue.members[0]).toEqual('staticMethod'); + expect(annotations[0].providers[0].useValue.members[0]).toEqual('staticMethod'); }); }); diff --git a/modules/@angular/compiler/src/directive_resolver.ts b/modules/@angular/compiler/src/directive_resolver.ts index 28c502fc5f..4f7cb5a219 100644 --- a/modules/@angular/compiler/src/directive_resolver.ts +++ b/modules/@angular/compiler/src/directive_resolver.ts @@ -63,20 +63,23 @@ export class DirectiveResolver { inputs.push(propName); } } else if (a instanceof OutputMetadata) { - if (isPresent(a.bindingPropertyName)) { - outputs.push(`${propName}: ${a.bindingPropertyName}`); + const output: OutputMetadata = a; + if (isPresent(output.bindingPropertyName)) { + outputs.push(`${propName}: ${output.bindingPropertyName}`); } else { outputs.push(propName); } } else if (a instanceof HostBindingMetadata) { - if (isPresent(a.hostPropertyName)) { - host[`[${a.hostPropertyName}]`] = propName; + const hostBinding: HostBindingMetadata = a; + if (isPresent(hostBinding.hostPropertyName)) { + host[`[${hostBinding.hostPropertyName}]`] = propName; } else { host[`[${propName}]`] = propName; } } else if (a instanceof HostListenerMetadata) { - var args = isPresent(a.args) ? (a.args).join(', ') : ''; - host[`(${a.eventName})`] = `${propName}(${args})`; + const hostListener: HostListenerMetadata = a; + var args = isPresent(hostListener.args) ? (hostListener.args).join(', ') : ''; + host[`(${hostListener.eventName})`] = `${propName}(${args})`; } else if (a instanceof QueryMetadata) { queries[propName] = a; } diff --git a/modules/@angular/compiler/src/metadata_resolver.ts b/modules/@angular/compiler/src/metadata_resolver.ts index 50e265eb93..04d26c7466 100644 --- a/modules/@angular/compiler/src/metadata_resolver.ts +++ b/modules/@angular/compiler/src/metadata_resolver.ts @@ -6,14 +6,14 @@ * found in the LICENSE file at https://angular.io/license */ -import {AnimationAnimateMetadata, AnimationEntryMetadata, AnimationGroupMetadata, AnimationKeyframesSequenceMetadata, AnimationMetadata, AnimationStateDeclarationMetadata, AnimationStateMetadata, AnimationStateTransitionMetadata, AnimationStyleMetadata, AnimationWithStepsMetadata, AttributeMetadata, ChangeDetectionStrategy, ComponentMetadata, HostMetadata, InjectMetadata, Injectable, ModuleWithProviders, OptionalMetadata, Provider, QueryMetadata, SchemaMetadata, SelfMetadata, SkipSelfMetadata, Type, ViewQueryMetadata, resolveForwardRef} from '@angular/core'; +import {AnimationAnimateMetadata, AnimationEntryMetadata, AnimationGroupMetadata, AnimationKeyframesSequenceMetadata, AnimationMetadata, AnimationStateDeclarationMetadata, AnimationStateMetadata, AnimationStateTransitionMetadata, AnimationStyleMetadata, AnimationWithStepsMetadata, AttributeMetadata, ChangeDetectionStrategy, ComponentMetadata, HostMetadata, InjectMetadata, Injectable, ModuleWithProviders, OptionalMetadata, Provider, QueryMetadata, SchemaMetadata, SelfMetadata, SkipSelfMetadata, Type, resolveForwardRef} from '@angular/core'; import {StringMapWrapper} from '../src/facade/collection'; import {assertArrayOfStrings, assertInterpolationSymbols} from './assertions'; import * as cpl from './compile_metadata'; import {DirectiveResolver} from './directive_resolver'; -import {isArray, isBlank, isPresent, isString, stringify} from './facade/lang'; +import {StringWrapper, isArray, isBlank, isPresent, isString, stringify} from './facade/lang'; import {Identifiers, resolveIdentifierToken} from './identifiers'; import {hasLifecycleHook} from './lifecycle_reflector'; import {NgModuleResolver} from './ng_module_resolver'; @@ -484,7 +484,7 @@ export class CompileMetadataResolver { let isSkipSelf = false; let isOptional = false; let query: QueryMetadata = null; - let viewQuery: ViewQueryMetadata = null; + let viewQuery: QueryMetadata = null; var token: any = null; if (isArray(param)) { (param).forEach((paramEntry) => { @@ -664,11 +664,16 @@ export class CompileMetadataResolver { return res; } + private _queryVarBindings(selector: any): string[] { + return StringWrapper.split(selector, /\s*,\s*/g); + } + + getQueryMetadata(q: QueryMetadata, propertyName: string, typeOrFunc: Type|Function): cpl.CompileQueryMetadata { var selectors: cpl.CompileTokenMetadata[]; - if (q.isVarBindingQuery) { - selectors = q.varBindings.map(varName => this.getTokenMetadata(varName)); + if (isString(q.selector)) { + selectors = this._queryVarBindings(q.selector).map(varName => this.getTokenMetadata(varName)); } else { if (!isPresent(q.selector)) { throw new Error( diff --git a/modules/@angular/compiler/testing/directive_resolver_mock.ts b/modules/@angular/compiler/testing/directive_resolver_mock.ts index f103d84f3f..772ba84da3 100644 --- a/modules/@angular/compiler/testing/directive_resolver_mock.ts +++ b/modules/@angular/compiler/testing/directive_resolver_mock.ts @@ -62,7 +62,7 @@ export class MockDirectiveResolver extends DirectiveResolver { let view = this._views.get(type); if (!view) { - view = metadata; + view = metadata; } let animations = view.animations; diff --git a/modules/@angular/compiler/testing/index.ts b/modules/@angular/compiler/testing/index.ts index ea151d9f2e..aed6935c45 100644 --- a/modules/@angular/compiler/testing/index.ts +++ b/modules/@angular/compiler/testing/index.ts @@ -26,7 +26,7 @@ export * from './directive_resolver_mock'; export * from './ng_module_resolver_mock'; export * from './pipe_resolver_mock'; -import {createPlatformFactory, ModuleWithComponentFactories, Injectable, CompilerOptions, COMPILER_OPTIONS, CompilerFactory, ComponentFactory, NgModuleFactory, Injector, NgModuleMetadata, NgModuleMetadataType, ComponentMetadata, ComponentMetadataType, DirectiveMetadata, DirectiveMetadataType, PipeMetadata, PipeMetadataType, Type, PlatformRef} from '@angular/core'; +import {createPlatformFactory, ModuleWithComponentFactories, Injectable, CompilerOptions, COMPILER_OPTIONS, CompilerFactory, NgModuleFactory, Injector, NgModuleMetadata, NgModule, ComponentMetadata, Component, DirectiveMetadata, Directive, Pipe, Type, PlatformRef} from '@angular/core'; import {MetadataOverride} from '@angular/core/testing'; import {TestingCompilerFactory, TestingCompiler} from './private_import_core'; import {platformCoreDynamic, RuntimeCompiler, DirectiveResolver, NgModuleResolver, PipeResolver} from '@angular/compiler'; @@ -70,25 +70,24 @@ export class TestingCompilerImpl implements TestingCompiler { return this._compiler.compileModuleAndAllComponentsAsync(moduleType); } - overrideModule(ngModule: Type, override: MetadataOverride): void { + overrideModule(ngModule: Type, override: MetadataOverride): void { const oldMetadata = this._moduleResolver.resolve(ngModule, false); this._moduleResolver.setNgModule( ngModule, this._overrider.overrideMetadata(NgModuleMetadata, oldMetadata, override)); } - overrideDirective(directive: Type, override: MetadataOverride): void { + overrideDirective(directive: Type, override: MetadataOverride): void { const oldMetadata = this._directiveResolver.resolve(directive, false); this._directiveResolver.setDirective( directive, this._overrider.overrideMetadata(DirectiveMetadata, oldMetadata, override)); } - overrideComponent(component: Type, override: MetadataOverride): void { + overrideComponent(component: Type, override: MetadataOverride): void { const oldMetadata = this._directiveResolver.resolve(component, false); this._directiveResolver.setDirective( component, this._overrider.overrideMetadata(ComponentMetadata, oldMetadata, override)); } - overridePipe(pipe: Type, override: MetadataOverride): void { + overridePipe(pipe: Type, override: MetadataOverride): void { const oldMetadata = this._pipeResolver.resolve(pipe, false); - this._pipeResolver.setPipe( - pipe, this._overrider.overrideMetadata(PipeMetadata, oldMetadata, override)); + this._pipeResolver.setPipe(pipe, this._overrider.overrideMetadata(Pipe, oldMetadata, override)); } clearCache(): void { this._compiler.clearCache(); } clearCacheFor(type: Type) { this._compiler.clearCacheFor(type); } diff --git a/modules/@angular/core/src/console.ts b/modules/@angular/core/src/console.ts index dfc0c08aee..4acc013f6b 100644 --- a/modules/@angular/core/src/console.ts +++ b/modules/@angular/core/src/console.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {Injectable} from './di/decorators'; +import {Injectable} from './di'; import {print, warn} from './facade/lang'; @Injectable() diff --git a/modules/@angular/core/src/di.ts b/modules/@angular/core/src/di.ts index 37bdbfb503..cc05afff72 100644 --- a/modules/@angular/core/src/di.ts +++ b/modules/@angular/core/src/di.ts @@ -12,11 +12,7 @@ * The `di` module provides dependency injection container services. */ -export {HostMetadata, InjectMetadata, InjectableMetadata, OptionalMetadata, SelfMetadata, SkipSelfMetadata} from './di/metadata'; - - -// we have to reexport * because Dart and TS export two different sets of types -export * from './di/decorators'; +export * from './di/metadata'; export {forwardRef, resolveForwardRef, ForwardRefFn} from './di/forward_ref'; diff --git a/modules/@angular/core/src/di/decorators.ts b/modules/@angular/core/src/di/decorators.ts deleted file mode 100644 index b756194549..0000000000 --- a/modules/@angular/core/src/di/decorators.ts +++ /dev/null @@ -1,109 +0,0 @@ -/** - * @license - * Copyright Google Inc. All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -import {makeDecorator, makeParamDecorator} from '../util/decorators'; - -import {HostMetadata, InjectMetadata, InjectableMetadata, OptionalMetadata, SelfMetadata, SkipSelfMetadata} from './metadata'; - - -/** - * Factory for creating {@link InjectMetadata}. - * @stable - */ -export interface InjectMetadataFactory { - (token: any): any; - new (token: any): InjectMetadata; -} - -/** - * Factory for creating {@link OptionalMetadata}. - * @stable - */ -export interface OptionalMetadataFactory { - (): any; - new (): OptionalMetadata; -} - -/** - * Factory for creating {@link InjectableMetadata}. - * @stable - */ -export interface InjectableMetadataFactory { - (): any; - new (): InjectableMetadata; -} - -/** - * Factory for creating {@link SelfMetadata}. - * @stable - */ -export interface SelfMetadataFactory { - (): any; - new (): SelfMetadata; -} - -/** - * Factory for creating {@link HostMetadata}. - * @stable - */ -export interface HostMetadataFactory { - (): any; - new (): HostMetadata; -} - -/** - * Factory for creating {@link SkipSelfMetadata}. - * @stable - */ -export interface SkipSelfMetadataFactory { - (): any; - new (): SkipSelfMetadata; -} - -/** - * Factory for creating {@link InjectMetadata}. - * @stable - * @Annotation - */ -export var Inject: InjectMetadataFactory = makeParamDecorator(InjectMetadata); - -/** - * Factory for creating {@link OptionalMetadata}. - * @stable - * @Annotation - */ -export var Optional: OptionalMetadataFactory = makeParamDecorator(OptionalMetadata); - -/** - * Factory for creating {@link InjectableMetadata}. - * @stable - * @Annotation - */ -export var Injectable: InjectableMetadataFactory = - makeDecorator(InjectableMetadata); - -/** - * Factory for creating {@link SelfMetadata}. - * @stable - * @Annotation - */ -export var Self: SelfMetadataFactory = makeParamDecorator(SelfMetadata); - -/** - * Factory for creating {@link HostMetadata}. - * @stable - * @Annotation - */ -export var Host: HostMetadataFactory = makeParamDecorator(HostMetadata); - -/** - * Factory for creating {@link SkipSelfMetadata}. - * @stable - * @Annotation - */ -export var SkipSelf: SkipSelfMetadataFactory = makeParamDecorator(SkipSelfMetadata); diff --git a/modules/@angular/core/src/di/metadata.ts b/modules/@angular/core/src/di/metadata.ts index a30e4f7b83..97074d3d83 100644 --- a/modules/@angular/core/src/di/metadata.ts +++ b/modules/@angular/core/src/di/metadata.ts @@ -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: + * `, + * directives: [ChildDirective] + * }) + * class ParentCmp { + * } + * + * @Component({ + * selector: 'app', + * providers: [OtherService], + * template: ` + * Parent: + * `, + * 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: - * `, - * directives: [ChildDirective] - * }) - * class ParentCmp { - * } - * - * @Component({ - * selector: 'app', - * providers: [OtherService], - * template: ` - * Parent: - * `, - * 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 +}; diff --git a/modules/@angular/core/src/di/opaque_token.ts b/modules/@angular/core/src/di/opaque_token.ts index 534b5deb01..2d728b13a7 100644 --- a/modules/@angular/core/src/di/opaque_token.ts +++ b/modules/@angular/core/src/di/opaque_token.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {Injectable} from './decorators'; +import {Injectable} from './metadata'; /** * Creates a token that can be used in a DI Provider. diff --git a/modules/@angular/core/src/di/reflective_provider.ts b/modules/@angular/core/src/di/reflective_provider.ts index 4e877fa832..f07fe36d7e 100644 --- a/modules/@angular/core/src/di/reflective_provider.ts +++ b/modules/@angular/core/src/di/reflective_provider.ts @@ -12,7 +12,7 @@ import {reflector} from '../reflection/reflection'; import {Type} from '../type'; import {resolveForwardRef} from './forward_ref'; -import {DependencyMetadata, HostMetadata, InjectMetadata, OptionalMetadata, SelfMetadata, SkipSelfMetadata} from './metadata'; +import {HostMetadata, InjectMetadata, OptionalMetadata, SelfMetadata, SkipSelfMetadata} from './metadata'; import {ClassProvider, ExistingProvider, FactoryProvider, Provider, TypeProvider, ValueProvider} from './provider'; import {InvalidProviderError, MixingMultiProvidersWithRegularProvidersError, NoAnnotationError} from './reflective_errors'; import {ReflectiveKey} from './reflective_key'; @@ -256,12 +256,6 @@ function _extractToken( } else if (paramMetadata instanceof SkipSelfMetadata) { lowerBoundVisibility = paramMetadata; - - } else if (paramMetadata instanceof DependencyMetadata) { - if (isPresent(paramMetadata.token)) { - token = paramMetadata.token; - } - depProps.push(paramMetadata); } } diff --git a/modules/@angular/core/src/linker/view_utils.ts b/modules/@angular/core/src/linker/view_utils.ts index 3615400f78..ab7ee46379 100644 --- a/modules/@angular/core/src/linker/view_utils.ts +++ b/modules/@angular/core/src/linker/view_utils.ts @@ -9,7 +9,7 @@ import {APP_ID} from '../application_tokens'; import {devModeEqual} from '../change_detection/change_detection'; import {UNINITIALIZED} from '../change_detection/change_detection_util'; -import {Inject, Injectable} from '../di/decorators'; +import {Inject, Injectable} from '../di'; import {ListWrapper} from '../facade/collection'; import {isBlank, isPresent, looseIdentical} from '../facade/lang'; import {ViewEncapsulation} from '../metadata/view'; diff --git a/modules/@angular/core/src/metadata.ts b/modules/@angular/core/src/metadata.ts index 1e504664e3..03ebad232f 100644 --- a/modules/@angular/core/src/metadata.ts +++ b/modules/@angular/core/src/metadata.ts @@ -11,1102 +11,33 @@ * to be used by the decorator versions of these annotations. */ -import {AttributeMetadata, ContentChildMetadata, ContentChildrenMetadata, QueryMetadata, ViewChildMetadata, ViewChildrenMetadata, ViewQueryMetadata} from './metadata/di'; -import {ComponentMetadata, ComponentMetadataType, DirectiveMetadata, DirectiveMetadataType, HostBindingMetadata, HostListenerMetadata, InputMetadata, OutputMetadata, PipeMetadata, PipeMetadataType} from './metadata/directives'; -import {ModuleWithProviders, NgModuleMetadata, NgModuleMetadataType, SchemaMetadata} from './metadata/ng_module'; +import {Attribute, ContentChild, ContentChildren, Query, ViewChild, ViewChildren} from './metadata/di'; +import {Component, Directive, HostBinding, HostListener, Input, Output, Pipe} from './metadata/directives'; +import {ModuleWithProviders, NgModule, SchemaMetadata} from './metadata/ng_module'; import {ViewEncapsulation} from './metadata/view'; import {Type} from './type'; -import {TypeDecorator, makeDecorator, makeParamDecorator, makePropDecorator} from './util/decorators'; +import {TypeDecorator, makeParamDecorator, makePropDecorator} from './util/decorators'; -export {ANALYZE_FOR_ENTRY_COMPONENTS, AttributeMetadata, ContentChildMetadata, ContentChildrenMetadata, QueryMetadata, ViewChildMetadata, ViewChildrenMetadata, ViewQueryMetadata} from './metadata/di'; -export {ComponentMetadata, ComponentMetadataType, DirectiveMetadata, DirectiveMetadataType, HostBindingMetadata, HostListenerMetadata, InputMetadata, OutputMetadata, PipeMetadata, PipeMetadataType} from './metadata/directives'; +export {ANALYZE_FOR_ENTRY_COMPONENTS, Attribute, ContentChild, ContentChildren, Query, ViewChild, ViewChildren} from './metadata/di'; +export {Component, Directive, HostBinding, HostListener, Input, Output, Pipe} from './metadata/directives'; export {AfterContentChecked, AfterContentInit, AfterViewChecked, AfterViewInit, DoCheck, OnChanges, OnDestroy, OnInit} from './metadata/lifecycle_hooks'; -export {CUSTOM_ELEMENTS_SCHEMA, ModuleWithProviders, NO_ERRORS_SCHEMA, NgModuleMetadata, NgModuleMetadataType, SchemaMetadata} from './metadata/ng_module'; +export {CUSTOM_ELEMENTS_SCHEMA, ModuleWithProviders, NO_ERRORS_SCHEMA, NgModule, SchemaMetadata} from './metadata/ng_module'; export {ViewEncapsulation} from './metadata/view'; -/** - * Interface for the {@link DirectiveMetadata} decorator function. - * - * See {@link DirectiveMetadataFactory}. - * - * @stable - */ -export interface DirectiveDecorator extends TypeDecorator {} - -/** - * Interface for the {@link ComponentMetadata} decorator function. - * - * See {@link ComponentFactory}. - * - * @stable - */ -export interface ComponentDecorator extends TypeDecorator {} - -/** - * Interface for the {@link NgModuleMetadata} decorator function. - * - * See {@link NgModuleMetadataFactory}. - * - * @stable - */ -export interface NgModuleDecorator extends TypeDecorator {} - - -/** - * {@link DirectiveMetadata} factory for creating annotations, decorators or DSL. - * - * ### Example as TypeScript Decorator - * - * {@example core/ts/metadata/metadata.ts region='directive'} - * - * ### Example as ES5 DSL - * - * ``` - * var MyDirective = ng - * .Directive({...}) - * .Class({ - * constructor: function() { - * ... - * } - * }) - * ``` - * - * ### Example as ES5 annotation - * - * ``` - * var MyDirective = function() { - * ... - * }; - * - * MyDirective.annotations = [ - * new ng.Directive({...}) - * ] - * ``` - * - * @stable - */ -export interface DirectiveMetadataFactory { - (obj: DirectiveMetadataType): DirectiveDecorator; - new (obj: DirectiveMetadataType): DirectiveMetadata; -} - -/** - * {@link ComponentMetadata} factory for creating annotations, decorators or DSL. - * - * ### Example as TypeScript Decorator - * - * {@example core/ts/metadata/metadata.ts region='component'} - * - * ### Example as ES5 DSL - * - * ``` - * var MyComponent = ng - * .Component({...}) - * .Class({ - * constructor: function() { - * ... - * } - * }) - * ``` - * - * ### Example as ES5 annotation - * - * ``` - * var MyComponent = function() { - * ... - * }; - * - * MyComponent.annotations = [ - * new ng.Component({...}) - * ] - * ``` - * - * @stable - */ -export interface ComponentMetadataFactory { - (obj: ComponentMetadataType): ComponentDecorator; - new (obj: ComponentMetadataType): ComponentMetadata; -} - -/** - * {@link AttributeMetadata} factory for creating annotations, decorators or DSL. - * - * ### Example as TypeScript Decorator - * - * {@example core/ts/metadata/metadata.ts region='attributeFactory'} - * - * ### Example as ES5 DSL - * - * ``` - * var MyComponent = ng - * .Component({...}) - * .Class({ - * constructor: [new ng.Attribute('title'), function(title) { - * ... - * }] - * }) - * ``` - * - * ### Example as ES5 annotation - * - * ``` - * var MyComponent = function(title) { - * ... - * }; - * - * MyComponent.annotations = [ - * new ng.Component({...}) - * ] - * MyComponent.parameters = [ - * [new ng.Attribute('title')] - * ] - * ``` - * - * @stable - */ -export interface AttributeMetadataFactory { - (name: string): TypeDecorator; - new (name: string): AttributeMetadata; -} - -/** - * Factory for {@link ContentChildren}. - * @stable - */ -export interface ContentChildrenMetadataFactory { - (selector: Type|Function|string, - {descendants, read}?: {descendants?: boolean, read?: any}): any; - new ( - selector: Type|Function|string, - {descendants, read}?: {descendants?: boolean, read?: any}): ContentChildrenMetadata; -} - -/** - * Factory for {@link ContentChild}. - * @stable - */ -export interface ContentChildMetadataFactory { - (selector: Type|Function|string, {read}?: {read?: any}): any; - new (selector: Type|Function|string, {read}?: {read?: any}): ContentChildMetadataFactory; -} - -/** - * Factory for {@link ViewChildren}. - * @stable - */ -export interface ViewChildrenMetadataFactory { - (selector: Type|Function|string, {read}?: {read?: any}): any; - new (selector: Type|Function|string, {read}?: {read?: any}): ViewChildrenMetadata; -} - -/** - * Factory for {@link ViewChild}. - * @stable - */ -export interface ViewChildMetadataFactory { - (selector: Type|Function|string, {read}?: {read?: any}): any; - new (selector: Type|Function|string, {read}?: {read?: any}): ViewChildMetadataFactory; -} - - -/** - * {@link PipeMetadata} factory for creating decorators. - * - * ### Example - * - * {@example core/ts/metadata/metadata.ts region='pipe'} - * @stable - */ -export interface PipeMetadataFactory { - (obj: PipeMetadataType): any; - new (obj: PipeMetadataType): any; -} - -/** - * {@link InputMetadata} factory for creating decorators. - * - * See {@link InputMetadata}. - * @stable - */ -export interface InputMetadataFactory { - (bindingPropertyName?: string): any; - new (bindingPropertyName?: string): any; -} - -/** - * {@link OutputMetadata} factory for creating decorators. - * - * See {@link OutputMetadata}. - * @stable - */ -export interface OutputMetadataFactory { - (bindingPropertyName?: string): any; - new (bindingPropertyName?: string): any; -} - -/** - * {@link HostBindingMetadata} factory function. - * @stable - */ -export interface HostBindingMetadataFactory { - (hostPropertyName?: string): any; - new (hostPropertyName?: string): any; -} - -/** - * {@link HostListenerMetadata} factory function. - * @stable - */ -export interface HostListenerMetadataFactory { - (eventName: string, args?: string[]): any; - new (eventName: string, args?: string[]): any; -} - -/** - * {@link NgModuleMetadata} factory for creating annotations, decorators or DSL. - * - * @stable - */ -export interface NgModuleMetadataFactory { - (obj?: NgModuleMetadataType): NgModuleDecorator; - new (obj?: NgModuleMetadataType): NgModuleMetadata; -} - -// TODO(alexeagle): remove the duplication of this doc. It is copied from ComponentMetadata. -/** - * Declare reusable UI building blocks for an application. - * - * Each Angular component requires a single `@Component` annotation. The `@Component` - * annotation specifies when a component is instantiated, and which properties and hostListeners it - * binds to. - * - * When a component is instantiated, Angular - * - creates a shadow DOM for the component. - * - loads the selected template into the shadow DOM. - * - creates all the injectable objects configured with `providers` and `viewProviders`. - * - * All template expressions and statements are then evaluated against the component instance. - * - * ## Lifecycle hooks - * - * When the component class implements some {@linkDocs guide/lifecycle-hooks} the - * callbacks are called by the change detection at defined points in time during the life of the - * component. - * - * ### Example - * - * {@example core/ts/metadata/metadata.ts region='component'} - * @stable - * @Annotation - */ -export var Component: ComponentMetadataFactory = - makeDecorator(ComponentMetadata); - -// TODO(alexeagle): remove the duplication of this doc. It is copied from DirectiveMetadata. -/** - * Directives allow you to attach behavior to elements in the DOM. - * - * {@link DirectiveMetadata}s with an embedded view are called {@link ComponentMetadata}s. - * - * A directive consists of a single directive annotation and a controller class. When the - * directive's `selector` matches - * elements in the DOM, the following steps occur: - * - * 1. For each directive, the `ElementInjector` attempts to resolve the directive's constructor - * arguments. - * 2. Angular instantiates directives for each matched element using `ElementInjector` in a - * depth-first order, - * as declared in the HTML. - * - * ## Understanding How Injection Works - * - * There are three stages of injection resolution. - * - *Pre-existing Injectors*: - * - The terminal {@link Injector} cannot resolve dependencies. It either throws an error or, if - * the dependency was - * specified as `@Optional`, returns `null`. - * - The platform injector resolves browser singleton resources, such as: cookies, title, - * location, and others. - * - *Component Injectors*: Each component instance has its own {@link Injector}, and they follow - * the same parent-child hierarchy - * as the component instances in the DOM. - * - *Element Injectors*: Each component instance has a Shadow DOM. Within the Shadow DOM each - * element has an `ElementInjector` - * which follow the same parent-child hierarchy as the DOM elements themselves. - * - * When a template is instantiated, it also must instantiate the corresponding directives in a - * depth-first order. The - * current `ElementInjector` resolves the constructor dependencies for each directive. - * - * Angular then resolves dependencies as follows, according to the order in which they appear in the - * {@link ComponentMetadata}: - * - * 1. Dependencies on the current element - * 2. Dependencies on element injectors and their parents until it encounters a Shadow DOM boundary - * 3. Dependencies on component injectors and their parents until it encounters the root component - * 4. Dependencies on pre-existing injectors - * - * - * The `ElementInjector` can inject other directives, element-specific special objects, or it can - * delegate to the parent - * injector. - * - * To inject other directives, declare the constructor parameter as: - * - `directive:DirectiveType`: a directive on the current element only - * - `@Host() directive:DirectiveType`: any directive that matches the type between the current - * element and the - * Shadow DOM root. - * - `@Query(DirectiveType) query:QueryList`: A live collection of direct child - * directives. - * - `@QueryDescendants(DirectiveType) query:QueryList`: A live collection of any - * child directives. - * - * To inject element-specific special objects, declare the constructor parameter as: - * - `element: ElementRef` to obtain a reference to logical element in the view. - * - `viewContainer: ViewContainerRef` to control child template instantiation, for - * {@link DirectiveMetadata} directives only - * - `bindingPropagation: BindingPropagation` to control change detection in a more granular way. - * - * ### Example - * - * The following example demonstrates how dependency injection resolves constructor arguments in - * practice. - * - * - * Assume this HTML template: - * - * ``` - *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- * ``` - * - * With the following `dependency` decorator and `SomeService` injectable class. - * - * ``` - * @Injectable() - * class SomeService { - * } - * - * @Directive({ - * selector: '[dependency]', - * inputs: [ - * 'id: dependency' - * ] - * }) - * class Dependency { - * id:string; - * } - * ``` - * - * Let's step through the different ways in which `MyDirective` could be declared... - * - * - * ### No injection - * - * Here the constructor is declared with no arguments, therefore nothing is injected into - * `MyDirective`. - * - * ``` - * @Directive({ selector: '[my-directive]' }) - * class MyDirective { - * constructor() { - * } - * } - * ``` - * - * This directive would be instantiated with no dependencies. - * - * - * ### Component-level injection - * - * Directives can inject any injectable instance from the closest component injector or any of its - * parents. - * - * Here, the constructor declares a parameter, `someService`, and injects the `SomeService` type - * from the parent - * component's injector. - * ``` - * @Directive({ selector: '[my-directive]' }) - * class MyDirective { - * constructor(someService: SomeService) { - * } - * } - * ``` - * - * This directive would be instantiated with a dependency on `SomeService`. - * - * - * ### Injecting a directive from the current element - * - * Directives can inject other directives declared on the current element. - * - * ``` - * @Directive({ selector: '[my-directive]' }) - * class MyDirective { - * constructor(dependency: Dependency) { - * expect(dependency.id).toEqual(3); - * } - * } - * ``` - * This directive would be instantiated with `Dependency` declared at the same element, in this case - * `dependency="3"`. - * - * ### Injecting a directive from any ancestor elements - * - * Directives can inject other directives declared on any ancestor element (in the current Shadow - * DOM), i.e. on the current element, the - * parent element, or its parents. - * ``` - * @Directive({ selector: '[my-directive]' }) - * class MyDirective { - * constructor(@Host() dependency: Dependency) { - * expect(dependency.id).toEqual(2); - * } - * } - * ``` - * - * `@Host` checks the current element, the parent, as well as its parents recursively. If - * `dependency="2"` didn't - * exist on the direct parent, this injection would - * have returned - * `dependency="1"`. - * - * - * ### Injecting a live collection of direct child directives - * - * - * A directive can also query for other child directives. Since parent directives are instantiated - * before child directives, a directive can't simply inject the list of child directives. Instead, - * the directive injects a {@link QueryList}, which updates its contents as children are added, - * removed, or moved by a directive that uses a {@link ViewContainerRef} such as a `ngFor`, an - * `ngIf`, or an `ngSwitch`. - * - * ``` - * @Directive({ selector: '[my-directive]' }) - * class MyDirective { - * constructor(@Query(Dependency) dependencies:QueryList) { - * } - * } - * ``` - * - * This directive would be instantiated with a {@link QueryList} which contains `Dependency` 4 and - * 6. Here, `Dependency` 5 would not be included, because it is not a direct child. - * - * ### Injecting a live collection of descendant directives - * - * By passing the descendant flag to `@Query` above, we can include the children of the child - * elements. - * - * ``` - * @Directive({ selector: '[my-directive]' }) - * class MyDirective { - * constructor(@Query(Dependency, {descendants: true}) dependencies:QueryList) { - * } - * } - * ``` - * - * This directive would be instantiated with a Query which would contain `Dependency` 4, 5 and 6. - * - * ### Optional injection - * - * The normal behavior of directives is to return an error when a specified dependency cannot be - * resolved. If you - * would like to inject `null` on unresolved dependency instead, you can annotate that dependency - * with `@Optional()`. - * This explicitly permits the author of a template to treat some of the surrounding directives as - * optional. - * - * ``` - * @Directive({ selector: '[my-directive]' }) - * class MyDirective { - * constructor(@Optional() dependency:Dependency) { - * } - * } - * ``` - * - * This directive would be instantiated with a `Dependency` directive found on the current element. - * If none can be - * found, the injector supplies `null` instead of throwing an error. - * - * ### Example - * - * Here we use a decorator directive to simply define basic tool-tip behavior. - * - * ``` - * @Directive({ - * selector: '[tooltip]', - * inputs: [ - * 'text: tooltip' - * ], - * host: { - * '(mouseenter)': 'onMouseEnter()', - * '(mouseleave)': 'onMouseLeave()' - * } - * }) - * class Tooltip{ - * text:string; - * overlay:Overlay; // NOT YET IMPLEMENTED - * overlayManager:OverlayManager; // NOT YET IMPLEMENTED - * - * constructor(overlayManager:OverlayManager) { - * this.overlayManager = overlayManager; - * } - * - * onMouseEnter() { - * // exact signature to be determined - * this.overlay = this.overlayManager.open(text, ...); - * } - * - * onMouseLeave() { - * this.overlay.close(); - * this.overlay = null; - * } - * } - * ``` - * In our HTML template, we can then add this behavior to a `
` or any other element with the - * `tooltip` selector, - * like so: - * - * ``` - *
- * ``` - * - * Directives can also control the instantiation, destruction, and positioning of inline template - * elements: - * - * A directive uses a {@link ViewContainerRef} to instantiate, insert, move, and destroy views at - * runtime. - * The {@link ViewContainerRef} is created as a result of `