diff --git a/modules/angular2/src/common/directives/ng_for.ts b/modules/angular2/src/common/directives/ng_for.ts index 2212c57473..18d2074b73 100644 --- a/modules/angular2/src/common/directives/ng_for.ts +++ b/modules/angular2/src/common/directives/ng_for.ts @@ -16,6 +16,18 @@ import { } from "../../core/change_detection/differs/default_iterable_differ"; import {BaseException} from "../../facade/exceptions"; +export class NgForRow { + constructor(public $implicit: any, public index: number, public count: number) {} + + get first(): boolean { return this.index === 0; } + + get last(): boolean { return this.index === this.count - 1; } + + get even(): boolean { return this.index % 2 === 0; } + + get odd(): boolean { return !this.even; } +} + /** * The `NgFor` directive instantiates a template once per item from an iterable. The context for * each instantiated template inherits from the outer context with the given loop variable set @@ -75,7 +87,7 @@ export class NgFor implements DoCheck { _ngForTrackBy: TrackByFn; private _differ: IterableDiffer; - constructor(private _viewContainer: ViewContainerRef, private _templateRef: TemplateRef, + constructor(private _viewContainer: ViewContainerRef, private _templateRef: TemplateRef, private _iterableDiffers: IterableDiffers, private _cdr: ChangeDetectorRef) {} set ngForOf(value: any) { @@ -90,7 +102,7 @@ export class NgFor implements DoCheck { } } - set ngForTemplate(value: TemplateRef) { + set ngForTemplate(value: TemplateRef) { if (isPresent(value)) { this._templateRef = value; } @@ -127,22 +139,19 @@ export class NgFor implements DoCheck { } for (var i = 0, ilen = this._viewContainer.length; i < ilen; i++) { - var viewRef = this._viewContainer.get(i); - viewRef.setLocal('first', i === 0); - viewRef.setLocal('last', i === ilen - 1); + var viewRef = >this._viewContainer.get(i); + viewRef.context.index = i; + viewRef.context.count = ilen; } changes.forEachIdentityChange((record) => { - var viewRef = this._viewContainer.get(record.currentIndex); - viewRef.setLocal('\$implicit', record.item); + var viewRef = >this._viewContainer.get(record.currentIndex); + viewRef.context.$implicit = record.item; }); } - private _perViewChange(view: EmbeddedViewRef, record: CollectionChangeRecord) { - view.setLocal('\$implicit', record.item); - view.setLocal('index', record.currentIndex); - view.setLocal('even', (record.currentIndex % 2 == 0)); - view.setLocal('odd', (record.currentIndex % 2 == 1)); + private _perViewChange(view: EmbeddedViewRef, record: CollectionChangeRecord) { + view.context.$implicit = record.item; } private _bulkRemove(tuples: RecordViewTuple[]): RecordViewTuple[] { @@ -153,7 +162,8 @@ export class NgFor implements DoCheck { var tuple = tuples[i]; // separate moved views from removed views. if (isPresent(tuple.record.currentIndex)) { - tuple.view = this._viewContainer.detach(tuple.record.previousIndex); + tuple.view = + >this._viewContainer.detach(tuple.record.previousIndex); movedTuples.push(tuple); } else { this._viewContainer.remove(tuple.record.previousIndex); @@ -169,8 +179,8 @@ export class NgFor implements DoCheck { if (isPresent(tuple.view)) { this._viewContainer.insert(tuple.view, tuple.record.currentIndex); } else { - tuple.view = - this._viewContainer.createEmbeddedView(this._templateRef, tuple.record.currentIndex); + tuple.view = this._viewContainer.createEmbeddedView( + this._templateRef, new NgForRow(null, null, null), tuple.record.currentIndex); } } return tuples; @@ -178,9 +188,9 @@ export class NgFor implements DoCheck { } class RecordViewTuple { - view: EmbeddedViewRef; + view: EmbeddedViewRef; record: any; - constructor(record: any, view: EmbeddedViewRef) { + constructor(record: any, view: EmbeddedViewRef) { this.record = record; this.view = view; } diff --git a/modules/angular2/src/common/directives/ng_if.ts b/modules/angular2/src/common/directives/ng_if.ts index bd30c07bb6..8ff804ba3a 100644 --- a/modules/angular2/src/common/directives/ng_if.ts +++ b/modules/angular2/src/common/directives/ng_if.ts @@ -27,7 +27,8 @@ import {isBlank} from 'angular2/src/facade/lang'; export class NgIf { private _prevCondition: boolean = null; - constructor(private _viewContainer: ViewContainerRef, private _templateRef: TemplateRef) {} + constructor(private _viewContainer: ViewContainerRef, private _templateRef: TemplateRef) { + } set ngIf(newCondition: any /* boolean */) { if (newCondition && (isBlank(this._prevCondition) || !this._prevCondition)) { diff --git a/modules/angular2/src/common/directives/ng_plural.ts b/modules/angular2/src/common/directives/ng_plural.ts index e5e892c862..4326f480f4 100644 --- a/modules/angular2/src/common/directives/ng_plural.ts +++ b/modules/angular2/src/common/directives/ng_plural.ts @@ -76,7 +76,7 @@ export abstract class NgLocalization { abstract getPluralCategory(value: any): s export class NgPluralCase { /** @internal */ _view: SwitchView; - constructor(@Attribute('ngPluralCase') public value: string, template: TemplateRef, + constructor(@Attribute('ngPluralCase') public value: string, template: TemplateRef, viewContainer: ViewContainerRef) { this._view = new SwitchView(viewContainer, template); } diff --git a/modules/angular2/src/common/directives/ng_switch.ts b/modules/angular2/src/common/directives/ng_switch.ts index 19a7292db3..4ad6719368 100644 --- a/modules/angular2/src/common/directives/ng_switch.ts +++ b/modules/angular2/src/common/directives/ng_switch.ts @@ -5,7 +5,8 @@ import {ListWrapper, Map} from 'angular2/src/facade/collection'; const _WHEN_DEFAULT = CONST_EXPR(new Object()); export class SwitchView { - constructor(private _viewContainerRef: ViewContainerRef, private _templateRef: TemplateRef) {} + constructor(private _viewContainerRef: ViewContainerRef, + private _templateRef: TemplateRef) {} create(): void { this._viewContainerRef.createEmbeddedView(this._templateRef); } @@ -175,7 +176,7 @@ export class NgSwitchWhen { _view: SwitchView; private _switch: NgSwitch; - constructor(viewContainer: ViewContainerRef, templateRef: TemplateRef, + constructor(viewContainer: ViewContainerRef, templateRef: TemplateRef, @Host() ngSwitch: NgSwitch) { this._switch = ngSwitch; this._view = new SwitchView(viewContainer, templateRef); @@ -195,7 +196,7 @@ export class NgSwitchWhen { */ @Directive({selector: '[ngSwitchDefault]'}) export class NgSwitchDefault { - constructor(viewContainer: ViewContainerRef, templateRef: TemplateRef, + constructor(viewContainer: ViewContainerRef, templateRef: TemplateRef, @Host() sswitch: NgSwitch) { sswitch._registerView(_WHEN_DEFAULT, new SwitchView(viewContainer, templateRef)); } diff --git a/modules/angular2/src/common/directives/ng_template_outlet.ts b/modules/angular2/src/common/directives/ng_template_outlet.ts index 38784bbad4..e8810f1a47 100644 --- a/modules/angular2/src/common/directives/ng_template_outlet.ts +++ b/modules/angular2/src/common/directives/ng_template_outlet.ts @@ -14,7 +14,7 @@ export class NgTemplateOutlet { constructor(private _viewContainerRef: ViewContainerRef) {} @Input() - set ngTemplateOutlet(templateRef: TemplateRef) { + set ngTemplateOutlet(templateRef: TemplateRef) { if (isPresent(this._insertedViewRef)) { this._viewContainerRef.remove(this._viewContainerRef.indexOf(this._insertedViewRef)); } diff --git a/modules/angular2/src/compiler/output/interpretive_view.ts b/modules/angular2/src/compiler/output/interpretive_view.ts index f00368d32b..84f6b451ed 100644 --- a/modules/angular2/src/compiler/output/interpretive_view.ts +++ b/modules/angular2/src/compiler/output/interpretive_view.ts @@ -17,7 +17,7 @@ export class InterpretiveAppViewInstanceFactory implements InstanceFactory { class _InterpretiveAppView extends AppView implements DynamicInstance { constructor(args: any[], public props: Map, public getters: Map, public methods: Map) { - super(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]); + super(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]); } createInternal(rootSelector: string | any): AppElement { var m = this.methods.get('createInternal'); diff --git a/modules/angular2/src/compiler/view_compiler/compile_view.ts b/modules/angular2/src/compiler/view_compiler/compile_view.ts index 32759d1f9c..6ead94a539 100644 --- a/modules/angular2/src/compiler/view_compiler/compile_view.ts +++ b/modules/angular2/src/compiler/view_compiler/compile_view.ts @@ -65,6 +65,8 @@ export class CompileView implements NameResolver { public literalMapCount = 0; public pipeCount = 0; + public componentContext: o.Expression; + constructor(public component: CompileDirectiveMetadata, public genConfig: CompilerConfig, public pipeMetas: CompilePipeMetadata[], public styles: o.Expression, public viewIndex: number, public declarationElement: CompileElement, @@ -90,6 +92,9 @@ export class CompileView implements NameResolver { } else { this.componentView = this.declarationElement.view.componentView; } + this.componentContext = + getPropertyInView(o.THIS_EXPR.prop('context'), this, this.componentView); + var viewQueries = new CompileTokenMap(); if (this.viewType === ViewType.COMPONENT) { var directiveInstance = o.THIS_EXPR.prop('context'); @@ -111,9 +116,8 @@ export class CompileView implements NameResolver { }); } this.viewQueries = viewQueries; - templateVariableBindings.forEach((entry) => { - this.locals.set(entry[1], o.THIS_EXPR.prop('locals').key(o.literal(entry[0]))); - }); + templateVariableBindings.forEach( + (entry) => { this.locals.set(entry[1], o.THIS_EXPR.prop('context').prop(entry[0])); }); if (!this.declarationElement.isNull()) { this.declarationElement.setEmbeddedView(this); diff --git a/modules/angular2/src/compiler/view_compiler/event_binder.ts b/modules/angular2/src/compiler/view_compiler/event_binder.ts index 90926b4946..20ed07379e 100644 --- a/modules/angular2/src/compiler/view_compiler/event_binder.ts +++ b/modules/angular2/src/compiler/view_compiler/event_binder.ts @@ -47,7 +47,8 @@ export class CompileEventListener { this._hasComponentHostListener = true; } this._method.resetDebugInfo(this.compileElement.nodeIndex, hostEvent); - var context = isPresent(directiveInstance) ? directiveInstance : o.THIS_EXPR.prop('context'); + var context = isPresent(directiveInstance) ? directiveInstance : + this.compileElement.view.componentContext; var actionStmts = convertCdStatementToIr(this.compileElement.view, context, hostEvent.handler); var lastIndex = actionStmts.length - 1; if (lastIndex >= 0) { diff --git a/modules/angular2/src/compiler/view_compiler/property_binder.ts b/modules/angular2/src/compiler/view_compiler/property_binder.ts index 266c60bfb5..223460d4e7 100644 --- a/modules/angular2/src/compiler/view_compiler/property_binder.ts +++ b/modules/angular2/src/compiler/view_compiler/property_binder.ts @@ -73,7 +73,7 @@ export function bindRenderText(boundText: BoundTextAst, compileNode: CompileNode var valueField = createBindFieldExpr(bindingIndex); view.detectChangesRenderPropertiesMethod.resetDebugInfo(compileNode.nodeIndex, boundText); - bind(view, currValExpr, valueField, boundText.value, o.THIS_EXPR.prop('context'), + bind(view, currValExpr, valueField, boundText.value, view.componentContext, [ o.THIS_EXPR.prop('renderer') .callMethod('setText', [compileNode.renderNode, currValExpr]) @@ -131,7 +131,7 @@ function bindAndWriteToRenderer(boundProps: BoundElementPropertyAst[], context: export function bindRenderInputs(boundProps: BoundElementPropertyAst[], compileElement: CompileElement): void { - bindAndWriteToRenderer(boundProps, o.THIS_EXPR.prop('context'), compileElement); + bindAndWriteToRenderer(boundProps, compileElement.view.componentContext, compileElement); } export function bindDirectiveHostProps(directiveAst: DirectiveAst, directiveInstance: o.Expression, @@ -184,7 +184,7 @@ export function bindDirectiveInputs(directiveAst: DirectiveAst, directiveInstanc statements.push( logBindingUpdateStmt(compileElement.renderNode, input.directiveName, currValExpr)); } - bind(view, currValExpr, fieldExpr, input.value, o.THIS_EXPR.prop('context'), statements, + bind(view, currValExpr, fieldExpr, input.value, view.componentContext, statements, detectChangesInInputsMethod); }); if (isOnPushComp) { diff --git a/modules/angular2/src/compiler/view_compiler/view_builder.ts b/modules/angular2/src/compiler/view_compiler/view_builder.ts index bb4d5a7ba8..63d505ea95 100644 --- a/modules/angular2/src/compiler/view_compiler/view_builder.ts +++ b/modules/angular2/src/compiler/view_compiler/view_builder.ts @@ -246,7 +246,9 @@ class ViewBuilderVisitor implements TemplateAstVisitor { compileElement.contentNodesByNgContentIndex.map(nodes => createFlatArray(nodes))); } this.view.createMethod.addStmt( - compViewExpr.callMethod('create', [codeGenContentNodes, o.NULL_EXPR]).toStmt()); + compViewExpr.callMethod('create', + [compileElement.getComponent(), codeGenContentNodes, o.NULL_EXPR]) + .toStmt()); } return null; } @@ -391,8 +393,6 @@ function createStaticNodeDebugInfo(node: CompileNode): o.Expression { function createViewClass(view: CompileView, renderCompTypeVar: o.ReadVarExpr, nodeDebugInfosVar: o.Expression): o.ClassStmt { - var emptyTemplateVariableBindings = - view.templateVariableBindings.map((entry) => [entry[0], o.NULL_EXPR]); var viewConstructorArgs = [ new o.FnParam(ViewConstructorVars.viewUtils.name, o.importType(Identifiers.ViewUtils)), new o.FnParam(ViewConstructorVars.parentInjector.name, o.importType(Identifiers.Injector)), @@ -403,7 +403,6 @@ function createViewClass(view: CompileView, renderCompTypeVar: o.ReadVarExpr, o.variable(view.className), renderCompTypeVar, ViewTypeEnum.fromValue(view.viewType), - o.literalMap(emptyTemplateVariableBindings), ViewConstructorVars.viewUtils, ViewConstructorVars.parentInjector, ViewConstructorVars.declarationEl, @@ -563,8 +562,10 @@ function addReturnValuefNotEmpty(statements: o.Statement[], value: o.Expression) } function getContextType(view: CompileView): o.Type { - var typeMeta = view.component.type; - return typeMeta.isHost ? o.DYNAMIC_TYPE : o.importType(typeMeta); + if (view.viewType === ViewType.COMPONENT) { + return o.importType(view.component.type); + } + return o.DYNAMIC_TYPE; } function getChangeDetectionMode(view: CompileView): ChangeDetectionStrategy { diff --git a/modules/angular2/src/core/debug/debug_node.ts b/modules/angular2/src/core/debug/debug_node.ts index aa6e80a865..138b30266a 100644 --- a/modules/angular2/src/core/debug/debug_node.ts +++ b/modules/angular2/src/core/debug/debug_node.ts @@ -26,8 +26,10 @@ export class DebugNode { return isPresent(this._debugInfo) ? this._debugInfo.component : null; } - get locals(): {[key: string]: any} { - return isPresent(this._debugInfo) ? this._debugInfo.locals : null; + get context(): any { return isPresent(this._debugInfo) ? this._debugInfo.context : null; } + + get references(): {[key: string]: any} { + return isPresent(this._debugInfo) ? this._debugInfo.references : null; } get providerTokens(): any[] { @@ -37,8 +39,6 @@ export class DebugNode { get source(): string { return isPresent(this._debugInfo) ? this._debugInfo.source : null; } inject(token: any): any { return this.injector.get(token); } - - getLocal(name: string): any { return this.locals[name]; } } export class DebugElement extends DebugNode { diff --git a/modules/angular2/src/core/linker/component_factory.ts b/modules/angular2/src/core/linker/component_factory.ts index d51521eedc..4e3ca09ed2 100644 --- a/modules/angular2/src/core/linker/component_factory.ts +++ b/modules/angular2/src/core/linker/component_factory.ts @@ -1,5 +1,5 @@ import {Injector} from 'angular2/src/core/di'; -import {Type, CONST, isPresent, isBlank} from 'angular2/src/facade/lang'; +import {Type, CONST, CONST_EXPR, isPresent, isBlank} from 'angular2/src/facade/lang'; import {unimplemented} from 'angular2/src/facade/exceptions'; import {ElementRef} from './element_ref'; import {ViewRef, ViewRef_} from './view_ref'; @@ -69,6 +69,8 @@ export class ComponentRef_ extends ComponentRef { onDestroy(callback: Function): void { this.hostView.onDestroy(callback); } } +const EMPTY_CONTEXT = CONST_EXPR(new Object()); + @CONST() export class ComponentFactory { constructor(public selector: string, private _viewFactory: Function, @@ -87,7 +89,7 @@ export class ComponentFactory { } // Note: Host views don't need a declarationAppElement! var hostView = this._viewFactory(vu, injector, null); - var hostElement = hostView.create(projectableNodes, rootSelectorOrNode); + var hostElement = hostView.create(EMPTY_CONTEXT, projectableNodes, rootSelectorOrNode); return new ComponentRef_(hostElement, this._componentType); } } diff --git a/modules/angular2/src/core/linker/debug_context.ts b/modules/angular2/src/core/linker/debug_context.ts index 986a5c45a5..fb52eab8ba 100644 --- a/modules/angular2/src/core/linker/debug_context.ts +++ b/modules/angular2/src/core/linker/debug_context.ts @@ -52,28 +52,21 @@ export class DebugContext implements RenderDebugInfo { get source(): string { return `${this._view.componentType.templateUrl}:${this._tplRow}:${this._tplCol}`; } - get locals(): {[key: string]: string} { + get references(): {[key: string]: any} { var varValues: {[key: string]: string} = {}; - // TODO(tbosch): right now, the semantics of debugNode.locals are - // that it contains the variables of all elements, not just - // the given one. We preserve this for now to not have a breaking - // change, but should change this later! - ListWrapper.forEachWithIndex( - this._view.staticNodeDebugInfos, - (staticNodeInfo: StaticNodeDebugInfo, nodeIndex: number) => { - var refs = staticNodeInfo.refTokens; - StringMapWrapper.forEach(refs, (refToken, refName) => { - var varValue; - if (isBlank(refToken)) { - varValue = isPresent(this._view.allNodes) ? this._view.allNodes[nodeIndex] : null; - } else { - varValue = this._view.injectorGet(refToken, nodeIndex, null); - } - varValues[refName] = varValue; - }); - }); - StringMapWrapper.forEach(this._view.locals, - (localValue, localName) => { varValues[localName] = localValue; }); + var staticNodeInfo = this._staticNodeInfo; + if (isPresent(staticNodeInfo)) { + var refs = staticNodeInfo.refTokens; + StringMapWrapper.forEach(refs, (refToken, refName) => { + var varValue; + if (isBlank(refToken)) { + varValue = isPresent(this._view.allNodes) ? this._view.allNodes[this._nodeIndex] : null; + } else { + varValue = this._view.injectorGet(refToken, this._nodeIndex, null); + } + varValues[refName] = varValue; + }); + } return varValues; } } diff --git a/modules/angular2/src/core/linker/template_ref.ts b/modules/angular2/src/core/linker/template_ref.ts index cd055d93f0..6a62e8e8ba 100644 --- a/modules/angular2/src/core/linker/template_ref.ts +++ b/modules/angular2/src/core/linker/template_ref.ts @@ -1,8 +1,11 @@ +import {CONST_EXPR, isBlank} from 'angular2/src/facade/lang'; import {ElementRef} from './element_ref'; import {AppElement} from './element'; import {AppView} from './view'; import {EmbeddedViewRef} from './view_ref'; +const EMPTY_CONTEXT = CONST_EXPR(new Object()); + /** * Represents an Embedded Template that can be used to instantiate Embedded Views. * @@ -15,7 +18,7 @@ import {EmbeddedViewRef} from './view_ref'; * {@link ViewContainerRef#createEmbeddedView}, which will create the View and attach it to the * View Container. */ -export abstract class TemplateRef { +export abstract class TemplateRef { /** * The location in the View where the Embedded View logically belongs to. * @@ -30,16 +33,19 @@ export abstract class TemplateRef { // TODO(i): rename to anchor or location get elementRef(): ElementRef { return null; } - abstract createEmbeddedView(): EmbeddedViewRef; + abstract createEmbeddedView(context: C): EmbeddedViewRef; } -export class TemplateRef_ extends TemplateRef { +export class TemplateRef_ extends TemplateRef { constructor(private _appElement: AppElement, private _viewFactory: Function) { super(); } - createEmbeddedView(): EmbeddedViewRef { - var view: AppView = this._viewFactory(this._appElement.parentView.viewUtils, - this._appElement.parentInjector, this._appElement); - view.create(null, null); + createEmbeddedView(context: C): EmbeddedViewRef { + var view: AppView = this._viewFactory(this._appElement.parentView.viewUtils, + this._appElement.parentInjector, this._appElement); + if (isBlank(context)) { + context = EMPTY_CONTEXT; + } + view.create(context, null, null); return view.ref; } diff --git a/modules/angular2/src/core/linker/view.ts b/modules/angular2/src/core/linker/view.ts index 002ea04ff8..1f842ec322 100644 --- a/modules/angular2/src/core/linker/view.ts +++ b/modules/angular2/src/core/linker/view.ts @@ -51,8 +51,6 @@ import { import {StaticNodeDebugInfo, DebugContext} from './debug_context'; import {ElementInjector} from './element_injector'; -const EMPTY_CONTEXT = CONST_EXPR(new Object()); - var _scope_check: WtfScopeFn = wtfCreateScope(`AppView#check(ascii id)`); /** @@ -60,7 +58,7 @@ var _scope_check: WtfScopeFn = wtfCreateScope(`AppView#check(ascii id)`); * */ export abstract class AppView { - ref: ViewRef_; + ref: ViewRef_; rootNodesOrAppElements: any[]; allNodes: any[]; disposables: Function[]; @@ -74,12 +72,6 @@ export abstract class AppView { // change detection will fail. cdState: ChangeDetectorState = ChangeDetectorState.NeverChecked; - /** - * The context against which data-binding expressions in this view are evaluated against. - * This is always a component instance. - */ - context: T = null; - projectableNodes: Array; destroyed: boolean = false; @@ -90,10 +82,11 @@ export abstract class AppView { private _hasExternalHostElement: boolean; + public context: T; + constructor(public clazz: any, public componentType: RenderComponentType, public type: ViewType, - public locals: {[key: string]: any}, public viewUtils: ViewUtils, - public parentInjector: Injector, public declarationAppElement: AppElement, - public cdMode: ChangeDetectionStrategy, + public viewUtils: ViewUtils, public parentInjector: Injector, + public declarationAppElement: AppElement, public cdMode: ChangeDetectionStrategy, public staticNodeDebugInfos: StaticNodeDebugInfo[]) { this.ref = new ViewRef_(this); if (type === ViewType.COMPONENT || type === ViewType.HOST) { @@ -103,27 +96,24 @@ export abstract class AppView { } } - create(givenProjectableNodes: Array, rootSelectorOrNode: string | any): AppElement { - var context; + create(context: T, givenProjectableNodes: Array, + rootSelectorOrNode: string | any): AppElement { + this.context = context; var projectableNodes; switch (this.type) { case ViewType.COMPONENT: - context = this.declarationAppElement.component; projectableNodes = ensureSlotCount(givenProjectableNodes, this.componentType.slotCount); break; case ViewType.EMBEDDED: - context = this.declarationAppElement.parentView.context; projectableNodes = this.declarationAppElement.parentView.projectableNodes; break; case ViewType.HOST: - context = EMPTY_CONTEXT; // Note: Don't ensure the slot count for the projectableNodes as we store // them only for the contained component view (which will later check the slot count...) projectableNodes = givenProjectableNodes; break; } this._hasExternalHostElement = isPresent(rootSelectorOrNode); - this.context = context; this.projectableNodes = projectableNodes; if (this.debugMode) { this._resetDebug(); @@ -277,12 +267,6 @@ export abstract class AppView { return _findLastRenderNode(lastNode); } - hasLocal(contextName: string): boolean { - return StringMapWrapper.contains(this.locals, contextName); - } - - setLocal(contextName: string, value: any): void { this.locals[contextName] = value; } - /** * Overwritten by implementations */ diff --git a/modules/angular2/src/core/linker/view_container_ref.ts b/modules/angular2/src/core/linker/view_container_ref.ts index 369a758022..dcac8e1852 100644 --- a/modules/angular2/src/core/linker/view_container_ref.ts +++ b/modules/angular2/src/core/linker/view_container_ref.ts @@ -62,7 +62,9 @@ export abstract class ViewContainerRef { * * Returns the {@link ViewRef} for the newly created View. */ - abstract createEmbeddedView(templateRef: TemplateRef, index?: number): EmbeddedViewRef; + // TODO(tbosch): Use a generic once ts2dart supports it. + abstract createEmbeddedView(templateRef: TemplateRef, context?: any, + index?: number): EmbeddedViewRef; /** * Instantiates a single {@link Component} and inserts its Host View into this container at the @@ -113,7 +115,7 @@ export abstract class ViewContainerRef { export class ViewContainerRef_ implements ViewContainerRef { constructor(private _element: AppElement) {} - get(index: number): EmbeddedViewRef { return this._element.nestedViews[index].ref; } + get(index: number): ViewRef { return this._element.nestedViews[index].ref; } get length(): number { var views = this._element.nestedViews; return isPresent(views) ? views.length : 0; @@ -127,8 +129,10 @@ export class ViewContainerRef_ implements ViewContainerRef { // TODO(rado): profile and decide whether bounds checks should be added // to the methods below. - createEmbeddedView(templateRef: TemplateRef, index: number = -1): EmbeddedViewRef { - var viewRef: EmbeddedViewRef = templateRef.createEmbeddedView(); + // TODO(tbosch): use a generic C once ts2dart supports it. + createEmbeddedView(templateRef: TemplateRef, context: any = null, + index: number = -1): EmbeddedViewRef { + var viewRef: EmbeddedViewRef = templateRef.createEmbeddedView(context); this.insert(viewRef, index); return viewRef; } @@ -153,13 +157,13 @@ export class ViewContainerRef_ implements ViewContainerRef { insert(viewRef: ViewRef, index: number = -1): ViewRef { var s = this._insertScope(); if (index == -1) index = this.length; - var viewRef_ = viewRef; + var viewRef_ = >viewRef; this._element.attachView(viewRef_.internalView, index); return wtfLeave(s, viewRef_); } indexOf(viewRef: ViewRef): number { - return ListWrapper.indexOf(this._element.nestedViews, (viewRef).internalView); + return ListWrapper.indexOf(this._element.nestedViews, (>viewRef).internalView); } /** @internal */ diff --git a/modules/angular2/src/core/linker/view_ref.ts b/modules/angular2/src/core/linker/view_ref.ts index 8f86cd45d4..aa90ad79bb 100644 --- a/modules/angular2/src/core/linker/view_ref.ts +++ b/modules/angular2/src/core/linker/view_ref.ts @@ -38,9 +38,9 @@ export abstract class ViewRef extends ChangeDetectorRef { * * ``` * - * ... we have two {@link ProtoViewRef}s: + * ... we have two {@link TemplateRef}s: * - * Outer {@link ProtoViewRef}: + * Outer {@link TemplateRef}: * ``` * Count: {{items.length}} *
    @@ -48,14 +48,14 @@ export abstract class ViewRef extends ChangeDetectorRef { *
* ``` * - * Inner {@link ProtoViewRef}: + * Inner {@link TemplateRef}: * ``` *
  • {{item}}
  • * ``` * - * Notice that the original template is broken down into two separate {@link ProtoViewRef}s. + * Notice that the original template is broken down into two separate {@link TemplateRef}s. * - * The outer/inner {@link ProtoViewRef}s are then assembled into views like so: + * The outer/inner {@link TemplateRef}s are then assembled into views like so: * * ``` * @@ -68,16 +68,8 @@ export abstract class ViewRef extends ChangeDetectorRef { * * ``` */ -export abstract class EmbeddedViewRef extends ViewRef { - /** - * Sets `value` of local variable called `variableName` in this View. - */ - abstract setLocal(variableName: string, value: any): void; - - /** - * Checks whether this view has a local variable called `variableName`. - */ - abstract hasLocal(variableName: string): boolean; +export abstract class EmbeddedViewRef extends ViewRef { + get context(): C { return unimplemented(); } get rootNodes(): any[] { return unimplemented(); }; @@ -87,10 +79,10 @@ export abstract class EmbeddedViewRef extends ViewRef { abstract destroy(); } -export class ViewRef_ implements EmbeddedViewRef { - constructor(private _view: AppView) { this._view = _view; } +export class ViewRef_ implements EmbeddedViewRef { + constructor(private _view: AppView) { this._view = _view; } - get internalView(): AppView { return this._view; } + get internalView(): AppView { return this._view; } /** * Return `ChangeDetectorRef` @@ -99,9 +91,7 @@ export class ViewRef_ implements EmbeddedViewRef { get rootNodes(): any[] { return this._view.flatRootNodes; } - setLocal(variableName: string, value: any): void { this._view.setLocal(variableName, value); } - - hasLocal(variableName: string): boolean { return this._view.hasLocal(variableName); } + get context() { return this._view.context; } get destroyed(): boolean { return this._view.destroyed; } diff --git a/modules/angular2/src/core/reflection/reflection_capabilities.dart b/modules/angular2/src/core/reflection/reflection_capabilities.dart index 2c1d98ea8a..3cd4b4a030 100644 --- a/modules/angular2/src/core/reflection/reflection_capabilities.dart +++ b/modules/angular2/src/core/reflection/reflection_capabilities.dart @@ -8,10 +8,28 @@ import 'package:angular2/src/facade/lang.dart'; import 'platform_reflection_capabilities.dart'; import 'types.dart'; +import '../linker/template_ref.dart'; + var DOT_REGEX = new RegExp('\\.'); class ReflectionCapabilities implements PlatformReflectionCapabilities { - ReflectionCapabilities([metadataReader]) {} + Map parameterizedTypeMapping = new Map(); + + ReflectionCapabilities([metadataReader]) { + // In Dart, there is no way of getting from a parameterized Type to + // the underlying non parameterized type. + // So we need to have a separate Map for the types that are generic + // and used in our DI... + parameterizedTypeMapping[reflectType(TemplateRef).qualifiedName] = TemplateRef; + } + + _typeFromMirror(TypeMirror typeMirror) { + var result = parameterizedTypeMapping[typeMirror.qualifiedName]; + if (result == null && typeMirror.hasReflectedType && typeMirror.reflectedType != dynamic) { + result = typeMirror.reflectedType; + } + return result; + } bool isReflectionEnabled() { return true; @@ -245,9 +263,8 @@ class ReflectionCapabilities implements PlatformReflectionCapabilities { List _convertParameter(ParameterMirror p) { var t = p.type; - var res = (!t.hasReflectedType || t.reflectedType == dynamic) - ? [] - : [t.reflectedType]; + var type = _typeFromMirror(t); + var res = type != null ? [type] : []; res.addAll(p.metadata.map((m) => m.reflectee)); return res; } diff --git a/modules/angular2/src/core/render/api.ts b/modules/angular2/src/core/render/api.ts index 627158c955..5e2c1f6d9f 100644 --- a/modules/angular2/src/core/render/api.ts +++ b/modules/angular2/src/core/render/api.ts @@ -11,7 +11,8 @@ export abstract class RenderDebugInfo { get injector(): Injector { return unimplemented(); } get component(): any { return unimplemented(); } get providerTokens(): any[] { return unimplemented(); } - get locals(): {[key: string]: string} { return unimplemented(); } + get references(): {[key: string]: any} { return unimplemented(); } + get context(): any { return unimplemented(); } get source(): string { return unimplemented(); } } diff --git a/modules/angular2/test/common/directives/ng_for_spec.ts b/modules/angular2/test/common/directives/ng_for_spec.ts index 2ce2ced7d9..89163d9aa1 100644 --- a/modules/angular2/test/common/directives/ng_for_spec.ts +++ b/modules/angular2/test/common/directives/ng_for_spec.ts @@ -512,7 +512,7 @@ class Foo { @Component({selector: 'test-cmp', directives: [NgFor, NgIf], template: ''}) class TestComponent { - @ContentChild(TemplateRef) contentTpl: TemplateRef; + @ContentChild(TemplateRef) contentTpl: TemplateRef; items: any; constructor() { this.items = [1, 2]; } trackById(index: number, item: any): string { return item['id']; } diff --git a/modules/angular2/test/common/directives/ng_template_outlet_spec.ts b/modules/angular2/test/common/directives/ng_template_outlet_spec.ts index 158188f206..e4480d754d 100644 --- a/modules/angular2/test/common/directives/ng_template_outlet_spec.ts +++ b/modules/angular2/test/common/directives/ng_template_outlet_spec.ts @@ -43,7 +43,7 @@ export function main() { fixture.detectChanges(); expect(fixture.nativeElement).toHaveText(''); - var refs = fixture.debugElement.children[0].getLocal('refs'); + var refs = fixture.debugElement.children[0].references['refs']; fixture.componentInstance.currentTplRef = refs.tplRefs.first; fixture.detectChanges(); @@ -62,7 +62,7 @@ export function main() { .then((fixture) => { fixture.detectChanges(); - var refs = fixture.debugElement.children[0].getLocal('refs'); + var refs = fixture.debugElement.children[0].references['refs']; fixture.componentInstance.currentTplRef = refs.tplRefs.first; fixture.detectChanges(); @@ -84,7 +84,7 @@ export function main() { .then((fixture) => { fixture.detectChanges(); - var refs = fixture.debugElement.children[0].getLocal('refs'); + var refs = fixture.debugElement.children[0].references['refs']; fixture.componentInstance.currentTplRef = refs.tplRefs.first; fixture.detectChanges(); @@ -104,10 +104,10 @@ export function main() { @Directive({selector: 'tpl-refs', exportAs: 'tplRefs'}) class CaptureTplRefs { - @ContentChildren(TemplateRef) tplRefs: QueryList; + @ContentChildren(TemplateRef) tplRefs: QueryList>; } @Component({selector: 'test-cmp', directives: [NgTemplateOutlet, CaptureTplRefs], template: ''}) class TestComponent { - currentTplRef: TemplateRef; + currentTplRef: TemplateRef; } diff --git a/modules/angular2/test/core/debug/debug_node_spec.ts b/modules/angular2/test/core/debug/debug_node_spec.ts index ffd5c27dd5..ea84167802 100644 --- a/modules/angular2/test/core/debug/debug_node_spec.ts +++ b/modules/angular2/test/core/debug/debug_node_spec.ts @@ -338,7 +338,7 @@ export function main() { .then((fixture) => { fixture.detectChanges(); - expect(fixture.debugElement.children[0].getLocal('alice')).toBeAnInstanceOf(MyDir); + expect(fixture.debugElement.children[0].references['alice']).toBeAnInstanceOf(MyDir); async.done(); }); diff --git a/modules/angular2/test/core/linker/change_detection_integration_spec.ts b/modules/angular2/test/core/linker/change_detection_integration_spec.ts index 0bf51e4194..0f804b7ce5 100644 --- a/modules/angular2/test/core/linker/change_detection_integration_spec.ts +++ b/modules/angular2/test/core/linker/change_detection_integration_spec.ts @@ -1351,11 +1351,14 @@ class OrderCheckDirective2 { constructor(public log: DirectiveLog, _check1: OrderCheckDirective1) {} } +class TestLocalsContext { + constructor(public someLocal: string) {} +} + @Directive({selector: '[testLocals]'}) class TestLocals { - constructor(templateRef: TemplateRef, vcRef: ViewContainerRef) { - var viewRef = vcRef.createEmbeddedView(templateRef); - viewRef.setLocal('someLocal', 'someLocalValue'); + constructor(templateRef: TemplateRef, vcRef: ViewContainerRef) { + vcRef.createEmbeddedView(templateRef, new TestLocalsContext('someLocalValue')); } } diff --git a/modules/angular2/test/core/linker/integration_spec.ts b/modules/angular2/test/core/linker/integration_spec.ts index 6b671d86a5..6763ccb71a 100644 --- a/modules/angular2/test/core/linker/integration_spec.ts +++ b/modules/angular2/test/core/linker/integration_spec.ts @@ -348,7 +348,7 @@ function declareTests(isJit: boolean) { fixture.debugElement.componentInstance.ctxProp = 'a'; fixture.detectChanges(); - var dir = fixture.debugElement.children[0].getLocal('dir'); + var dir = fixture.debugElement.children[0].references['dir']; expect(dir.dirProp).toEqual('aa'); async.done(); }); @@ -473,7 +473,7 @@ function declareTests(isJit: boolean) { tcb.overrideView( MyComp, new ViewMetadata({ template: - '', + '', directives: [SomeViewport] })) @@ -509,7 +509,7 @@ function declareTests(isJit: boolean) { tcb.overrideView( MyComp, new ViewMetadata({ template: - '{{greeting}}', + '{{greeting}}', directives: [SomeViewport] })) @@ -558,7 +558,7 @@ function declareTests(isJit: boolean) { .createAsync(MyComp) .then((fixture) => { - expect(fixture.debugElement.children[0].children[0].getLocal('alice')) + expect(fixture.debugElement.children[0].children[0].references['alice']) .toBeAnInstanceOf(ChildComp); async.done(); @@ -574,7 +574,7 @@ function declareTests(isJit: boolean) { .createAsync(MyComp) .then((fixture) => { - expect(fixture.debugElement.children[0].children[0].getLocal('localdir')) + expect(fixture.debugElement.children[0].children[0].references['localdir']) .toBeAnInstanceOf(ExportDir); async.done(); @@ -613,11 +613,13 @@ function declareTests(isJit: boolean) { .createAsync(MyComp) .then((fixture) => { - var childCmp = fixture.debugElement.children[0].children[0]; + var pEl = fixture.debugElement.children[0]; - expect(childCmp.getLocal('alice')).toBeAnInstanceOf(ChildComp); - expect(childCmp.getLocal('bob')).toBeAnInstanceOf(ChildComp); - expect(childCmp.getLocal('alice')).not.toBe(childCmp.getLocal('bob')); + var alice = pEl.children[0].references['alice']; + var bob = pEl.children[1].references['bob']; + expect(alice).toBeAnInstanceOf(ChildComp); + expect(bob).toBeAnInstanceOf(ChildComp); + expect(alice).not.toBe(bob); async.done(); })})); @@ -633,7 +635,7 @@ function declareTests(isJit: boolean) { .createAsync(MyComp) .then((fixture) => { - expect(fixture.debugElement.children[0].getLocal('alice')) + expect(fixture.debugElement.children[0].references['alice']) .toBeAnInstanceOf(ChildComp); async.done(); @@ -650,7 +652,7 @@ function declareTests(isJit: boolean) { .then((fixture) => { var value = - fixture.debugElement.children[0].children[0].getLocal('alice'); + fixture.debugElement.children[0].children[0].references['alice']; expect(value).not.toBe(null); expect(value.tagName.toLowerCase()).toEqual('div'); @@ -666,7 +668,7 @@ function declareTests(isJit: boolean) { .createAsync(MyComp) .then((fixture) => { - var value = fixture.debugElement.childNodes[0].getLocal('alice'); + var value = fixture.debugElement.childNodes[0].references['alice']; expect(value).toBeAnInstanceOf(TemplateRef_); async.done(); @@ -682,7 +684,7 @@ function declareTests(isJit: boolean) { .createAsync(MyComp) .then((fixture) => { - expect(fixture.debugElement.children[0].children[0].getLocal('superAlice')) + expect(fixture.debugElement.children[0].children[0].references['superAlice']) .toBeAnInstanceOf(ChildComp); async.done(); @@ -727,7 +729,7 @@ function declareTests(isJit: boolean) { .createAsync(MyComp) .then((fixture) => { - var cmp = fixture.debugElement.children[0].getLocal('cmp'); + var cmp = fixture.debugElement.children[0].references['cmp']; fixture.detectChanges(); expect(cmp.numberOfChecks).toEqual(1); @@ -753,7 +755,7 @@ function declareTests(isJit: boolean) { .createAsync(MyComp) .then((fixture) => { - var cmp = fixture.debugElement.children[0].getLocal('cmp'); + var cmp = fixture.debugElement.children[0].references['cmp']; fixture.debugElement.componentInstance.ctxProp = "one"; fixture.detectChanges(); @@ -800,7 +802,7 @@ function declareTests(isJit: boolean) { .createAsync(MyComp) .then((fixture) => { - var cmp = fixture.debugElement.children[0].getLocal('cmp'); + var cmp = fixture.debugElement.children[0].references['cmp']; fixture.debugElement.componentInstance.ctxProp = "one"; fixture.detectChanges(); @@ -826,7 +828,7 @@ function declareTests(isJit: boolean) { .createAsync(MyComp) .then((fixture) => { - var cmp = fixture.debugElement.children[0].getLocal('cmp'); + var cmp = fixture.debugElement.children[0].references['cmp']; fixture.debugElement.componentInstance.ctxProp = "one"; fixture.detectChanges(); @@ -852,7 +854,7 @@ function declareTests(isJit: boolean) { tcb.createAsync(MyComp).then(root => { fixture = root; }); tick(); - var cmp: PushCmpWithAsyncPipe = fixture.debugElement.children[0].getLocal('cmp'); + var cmp: PushCmpWithAsyncPipe = fixture.debugElement.children[0].references['cmp']; fixture.detectChanges(); expect(cmp.numberOfChecks).toEqual(1); @@ -871,25 +873,28 @@ function declareTests(isJit: boolean) { it('should create a component that injects an @Host', inject([TestComponentBuilder, AsyncTestCompleter], - (tcb: TestComponentBuilder, async) => { - tcb.overrideView(MyComp, new ViewMetadata({ - template: ` + (tcb: TestComponentBuilder, + async) => {tcb.overrideView(MyComp, new ViewMetadata({ + template: `

    `, - directives: [SomeDirective, CompWithHost] - })) + directives: [SomeDirective, CompWithHost] + })) - .createAsync(MyComp) - .then((fixture) => { + .createAsync(MyComp) + .then((fixture) => { - var childComponent = fixture.debugElement.children[0].getLocal('child'); - expect(childComponent.myHost).toBeAnInstanceOf(SomeDirective); + var childComponent = fixture.debugElement.children[0] + .children[0] + .children[0] + .references['child']; + expect(childComponent.myHost).toBeAnInstanceOf(SomeDirective); - async.done(); - })})); + async.done(); + })})); it('should create a component that injects an @Host through viewcontainer directive', inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => { @@ -909,7 +914,7 @@ function declareTests(isJit: boolean) { var tc = fixture.debugElement.children[0].children[0].children[0]; - var childComponent = tc.getLocal('child'); + var childComponent = tc.references['child']; expect(childComponent.myHost).toBeAnInstanceOf(SomeDirective); async.done(); @@ -1235,7 +1240,7 @@ function declareTests(isJit: boolean) { })) .createAsync(MyComp) .then((fixture) => { - var comp = fixture.debugElement.children[0].getLocal("consuming"); + var comp = fixture.debugElement.children[0].children[0].references["consuming"]; expect(comp.injectable).toBeAnInstanceOf(InjectableService); async.done(); @@ -1253,7 +1258,7 @@ function declareTests(isJit: boolean) { })) .createAsync(DirectiveProvidingInjectableInView) .then((fixture) => { - var comp = fixture.debugElement.children[0].getLocal("consuming"); + var comp = fixture.debugElement.children[0].references["consuming"]; expect(comp.injectable).toBeAnInstanceOf(InjectableService); async.done(); @@ -1283,7 +1288,7 @@ function declareTests(isJit: boolean) { .createAsync(MyComp) .then((fixture) => { - var comp = fixture.debugElement.children[0].getLocal("dir"); + var comp = fixture.debugElement.children[0].children[0].references["dir"]; expect(comp.directive.injectable).toBeAnInstanceOf(InjectableService); async.done(); @@ -1341,7 +1346,7 @@ function declareTests(isJit: boolean) { })) .createAsync(MyComp) .then((fixture) => { - var providing = fixture.debugElement.children[0].getLocal("providing"); + var providing = fixture.debugElement.children[0].references["providing"]; expect(providing.created).toBe(false); fixture.debugElement.componentInstance.ctxBoolProp = true; @@ -1444,7 +1449,7 @@ function declareTests(isJit: boolean) { expect((c.injector).get).toBeTruthy(); expect(c.source).toContain(":0:7"); expect(c.context).toBe(fixture.debugElement.componentInstance); - expect(c.locals["local"]).toBeDefined(); + expect(c.references["local"]).toBeDefined(); } async.done(); @@ -1498,7 +1503,7 @@ function declareTests(isJit: boolean) { expect(DOM.nodeName(c.componentRenderElement).toUpperCase()).toEqual("DIV"); expect((c.injector).get).toBeTruthy(); expect(c.context).toBe(fixture.debugElement.componentInstance); - expect(c.locals["local"]).toBeDefined(); + expect(c.references["local"]).toBeDefined(); } }))); } @@ -2137,12 +2142,16 @@ class ChildComp2 { } } +class SomeViewportContext { + constructor(public someTmpl: string) {} +} + @Directive({selector: '[some-viewport]'}) @Injectable() class SomeViewport { - constructor(container: ViewContainerRef, templateRef: TemplateRef) { - container.createEmbeddedView(templateRef).setLocal('some-tmpl', 'hello'); - container.createEmbeddedView(templateRef).setLocal('some-tmpl', 'again'); + constructor(container: ViewContainerRef, templateRef: TemplateRef) { + container.createEmbeddedView(templateRef, new SomeViewportContext('hello')); + container.createEmbeddedView(templateRef, new SomeViewportContext('again')); } } @@ -2277,11 +2286,15 @@ class NeedsPublicApi { constructor(@Host() api: PublicApi) { expect(api instanceof PrivateImpl).toBe(true); } } +class ToolbarContext { + constructor(public toolbarProp: string) {} +} + @Directive({selector: '[toolbarpart]'}) @Injectable() class ToolbarPart { - templateRef: TemplateRef; - constructor(templateRef: TemplateRef) { this.templateRef = templateRef; } + templateRef: TemplateRef; + constructor(templateRef: TemplateRef) { this.templateRef = templateRef; } } @Directive({selector: '[toolbarVc]', inputs: ['toolbarVc']}) @@ -2291,8 +2304,7 @@ class ToolbarViewContainer { constructor(vc: ViewContainerRef) { this.vc = vc; } set toolbarVc(part: ToolbarPart) { - var view = this.vc.createEmbeddedView(part.templateRef, 0); - view.setLocal('toolbarProp', 'From toolbar'); + this.vc.createEmbeddedView(part.templateRef, new ToolbarContext('From toolbar'), 0); } } @@ -2453,9 +2465,9 @@ class ChildConsumingEventBus { @Directive({selector: '[someImpvp]', inputs: ['someImpvp']}) @Injectable() class SomeImperativeViewport { - view: EmbeddedViewRef; + view: EmbeddedViewRef; anchor; - constructor(public vc: ViewContainerRef, public templateRef: TemplateRef, + constructor(public vc: ViewContainerRef, public templateRef: TemplateRef, @Inject(ANCHOR_ELEMENT) anchor) { this.view = null; this.anchor = anchor; diff --git a/modules/angular2/test/core/linker/projection_integration_spec.ts b/modules/angular2/test/core/linker/projection_integration_spec.ts index f5797f7d1c..66f82f6795 100644 --- a/modules/angular2/test/core/linker/projection_integration_spec.ts +++ b/modules/angular2/test/core/linker/projection_integration_spec.ts @@ -691,15 +691,15 @@ class MultipleContentTagsComponent { @Directive({selector: '[manual]'}) class ManualViewportDirective { - constructor(public vc: ViewContainerRef, public templateRef: TemplateRef) {} - show() { this.vc.createEmbeddedView(this.templateRef, 0); } + constructor(public vc: ViewContainerRef, public templateRef: TemplateRef) {} + show() { this.vc.createEmbeddedView(this.templateRef); } hide() { this.vc.clear(); } } @Directive({selector: '[project]'}) class ProjectDirective { constructor(public vc: ViewContainerRef) {} - show(templateRef: TemplateRef) { this.vc.createEmbeddedView(templateRef, 0); } + show(templateRef: TemplateRef) { this.vc.createEmbeddedView(templateRef); } hide() { this.vc.clear(); } } diff --git a/modules/angular2/test/core/linker/query_integration_spec.ts b/modules/angular2/test/core/linker/query_integration_spec.ts index c11b7af6bd..55e66be325 100644 --- a/modules/angular2/test/core/linker/query_integration_spec.ts +++ b/modules/angular2/test/core/linker/query_integration_spec.ts @@ -68,7 +68,7 @@ export function main() { .then((view) => { view.detectChanges(); - var q = view.debugElement.children[0].getLocal('q'); + var q = view.debugElement.children[0].references['q']; view.detectChanges(); @@ -90,7 +90,7 @@ export function main() { view.debugElement.componentInstance.shouldShow = true; view.detectChanges(); - var q = view.debugElement.children[0].getLocal('q'); + var q = view.debugElement.children[0].references['q']; expect(q.log).toEqual([["setter", "foo"], ["init", "foo"], ["check", "foo"]]); @@ -117,7 +117,7 @@ export function main() { .createAsync(MyComp) .then((view) => { view.detectChanges(); - var q = view.debugElement.children[0].getLocal('q'); + var q = view.debugElement.children[0].references['q']; expect(q.log).toEqual([["setter", "foo"], ["init", "foo"], ["check", "foo"]]); @@ -146,7 +146,7 @@ export function main() { .createAsync(MyComp) .then((view) => { view.detectChanges(); - var q = view.debugElement.children[0].getLocal('q'); + var q = view.debugElement.children[0].references['q']; expect(q.log).toEqual([["setter", "foo"], ["init", "foo"], ["check", "foo"]]); @@ -268,17 +268,17 @@ export function main() { describe('query for TemplateRef', () => { it('should find TemplateRefs in the light and shadow dom', inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => { - var template = ''; + var template = ''; tcb.overrideTemplate(MyComp, template) .createAsync(MyComp) .then((view) => { view.detectChanges(); var needsTpl: NeedsTpl = view.debugElement.children[0].inject(NeedsTpl); - expect(needsTpl.vc.createEmbeddedView(needsTpl.query.first).hasLocal('light')) - .toBe(true); - expect(needsTpl.vc.createEmbeddedView(needsTpl.viewQuery.first).hasLocal('shadow')) - .toBe(true); + expect(needsTpl.vc.createEmbeddedView(needsTpl.query.first).rootNodes[0]) + .toHaveText('light'); + expect(needsTpl.vc.createEmbeddedView(needsTpl.viewQuery.first).rootNodes[0]) + .toHaveText('shadow'); async.done(); }); @@ -287,18 +287,18 @@ export function main() { it('should find named TemplateRefs', inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => { var template = - ''; + ''; tcb.overrideTemplate(MyComp, template) .createAsync(MyComp) .then((view) => { view.detectChanges(); var needsTpl: NeedsNamedTpl = view.debugElement.children[0].inject(NeedsNamedTpl); - expect(needsTpl.vc.createEmbeddedView(needsTpl.contentTpl).hasLocal('light')) - .toBe(true); - expect(needsTpl.vc.createEmbeddedView(needsTpl.viewTpl).hasLocal('shadow')) - .toBe(true); + expect(needsTpl.vc.createEmbeddedView(needsTpl.contentTpl).rootNodes[0]) + .toHaveText('light'); + expect(needsTpl.vc.createEmbeddedView(needsTpl.viewTpl).rootNodes[0]) + .toHaveText('shadow') - async.done(); + async.done(); }); })); }); @@ -407,7 +407,7 @@ export function main() { tcb.overrideTemplate(MyComp, template) .createAsync(MyComp) .then((view) => { - var q = view.debugElement.children[0].getLocal("q"); + var q = view.debugElement.children[0].references["q"]; view.detectChanges(); ObservableWrapper.subscribe(q.query.changes, (_) => { @@ -432,8 +432,8 @@ export function main() { tcb.overrideTemplate(MyComp, template) .createAsync(MyComp) .then((view) => { - var q1 = view.debugElement.children[0].getLocal("q1"); - var q2 = view.debugElement.children[0].getLocal("q2"); + var q1 = view.debugElement.children[0].references["q1"]; + var q2 = view.debugElement.children[0].children[0].references["q2"]; var firedQ2 = false; @@ -457,7 +457,7 @@ export function main() { view.debugElement.componentInstance.shouldShow = true; view.detectChanges(); - var q: NeedsQuery = view.debugElement.children[0].getLocal('q'); + var q: NeedsQuery = view.debugElement.children[0].references['q']; expect(q.query.length).toEqual(1); @@ -467,7 +467,7 @@ export function main() { view.debugElement.componentInstance.shouldShow = true; view.detectChanges(); - var q2: NeedsQuery = view.debugElement.children[0].getLocal('q'); + var q2: NeedsQuery = view.debugElement.children[0].references['q']; expect(q2.query.length).toEqual(1); @@ -487,7 +487,7 @@ export function main() { tcb.overrideTemplate(MyComp, template) .createAsync(MyComp) .then((view) => { - var q = view.debugElement.children[0].getLocal("q"); + var q = view.debugElement.children[0].references["q"]; view.debugElement.componentInstance.list = ['1d', '2d']; @@ -510,7 +510,7 @@ export function main() { tcb.overrideTemplate(MyComp, template) .createAsync(MyComp) .then((view) => { - var q = view.debugElement.children[0].getLocal("q"); + var q = view.debugElement.children[0].references["q"]; view.detectChanges(); expect(q.query.first.text).toEqual("one"); @@ -530,7 +530,7 @@ export function main() { tcb.overrideTemplate(MyComp, template) .createAsync(MyComp) .then((view) => { - var q = view.debugElement.children[0].getLocal("q"); + var q = view.debugElement.children[0].references["q"]; view.debugElement.componentInstance.list = ['1d', '2d']; @@ -557,7 +557,7 @@ export function main() { tcb.overrideTemplate(MyComp, template) .createAsync(MyComp) .then((view) => { - var q = view.debugElement.children[0].getLocal("q"); + var q = view.debugElement.children[0].references["q"]; view.debugElement.componentInstance.list = ['1d', '2d']; @@ -594,7 +594,7 @@ export function main() { tcb.overrideTemplate(MyComp, template) .createAsync(MyComp) .then((view) => { - var q: NeedsViewQueryByLabel = view.debugElement.children[0].getLocal("q"); + var q: NeedsViewQueryByLabel = view.debugElement.children[0].references["q"]; view.detectChanges(); expect(q.query.first.nativeElement).toHaveText("text"); @@ -612,7 +612,7 @@ export function main() { .then((view) => { view.detectChanges(); - var q = view.debugElement.children[0].getLocal('q'); + var q = view.debugElement.children[0].references['q']; view.detectChanges(); @@ -633,7 +633,7 @@ export function main() { tcb.overrideTemplate(MyComp, template) .createAsync(MyComp) .then((view) => { - var q: NeedsViewQuery = view.debugElement.children[0].getLocal("q"); + var q: NeedsViewQuery = view.debugElement.children[0].references["q"]; view.detectChanges(); @@ -650,7 +650,7 @@ export function main() { tcb.overrideTemplate(MyComp, template) .createAsync(MyComp) .then((view) => { - var q: NeedsViewQuery = view.debugElement.children[0].getLocal("q"); + var q: NeedsViewQuery = view.debugElement.children[0].references["q"]; view.detectChanges(); @@ -667,7 +667,7 @@ export function main() { tcb.overrideTemplate(MyComp, template) .createAsync(MyComp) .then((view) => { - var q: NeedsViewQueryIf = view.debugElement.children[0].getLocal("q"); + var q: NeedsViewQueryIf = view.debugElement.children[0].references["q"]; view.detectChanges(); @@ -690,7 +690,7 @@ export function main() { tcb.overrideTemplate(MyComp, template) .createAsync(MyComp) .then((view) => { - var q: NeedsViewQueryNestedIf = view.debugElement.children[0].getLocal("q"); + var q: NeedsViewQueryNestedIf = view.debugElement.children[0].references["q"]; view.detectChanges(); @@ -715,7 +715,7 @@ export function main() { tcb.overrideTemplate(MyComp, template) .createAsync(MyComp) .then((view) => { - var q: NeedsViewQueryOrder = view.debugElement.children[0].getLocal("q"); + var q: NeedsViewQueryOrder = view.debugElement.children[0].references["q"]; view.detectChanges(); @@ -738,7 +738,8 @@ export function main() { tcb.overrideTemplate(MyComp, template) .createAsync(MyComp) .then((view) => { - var q: NeedsViewQueryOrderWithParent = view.debugElement.children[0].getLocal("q"); + var q: NeedsViewQueryOrderWithParent = + view.debugElement.children[0].references["q"]; view.detectChanges(); @@ -761,7 +762,7 @@ export function main() { tcb.overrideTemplate(MyComp, template) .createAsync(MyComp) .then((view) => { - var q: NeedsViewQueryOrder = view.debugElement.children[0].getLocal('q'); + var q: NeedsViewQueryOrder = view.debugElement.children[0].references['q']; // no significance to 50, just a reasonably large cycle. for (var i = 0; i < 50; i++) { @@ -785,7 +786,7 @@ export function main() { .then((view) => { view.detectChanges(); - var q = view.debugElement.children[0].getLocal('q'); + var q = view.debugElement.children[0].references['q']; expect(q.query1).toBeDefined(); expect(q.query2).toBeDefined(); expect(q.query3).toBeDefined(); @@ -897,7 +898,7 @@ class NeedsFourQueries { @Component({ selector: 'needs-query-desc', directives: [NgFor], - template: '
    {{dir.text}}|
    ' + template: '
    {{dir.text}}|
    ' }) @Injectable() class NeedsQueryDesc { @@ -1024,21 +1025,22 @@ class NeedsViewQueryOrderWithParent { } } -@Component({selector: 'needs-tpl', template: ''}) +@Component({selector: 'needs-tpl', template: ''}) class NeedsTpl { - viewQuery: QueryList; - query: QueryList; - constructor(@ViewQuery(TemplateRef) viewQuery: QueryList, - @Query(TemplateRef) query: QueryList, public vc: ViewContainerRef) { + viewQuery: QueryList>; + query: QueryList>; + constructor(@ViewQuery(TemplateRef) viewQuery: QueryList>, + @Query(TemplateRef) query: QueryList>, + public vc: ViewContainerRef) { this.viewQuery = viewQuery; this.query = query; } } -@Component({selector: 'needs-named-tpl', template: ''}) +@Component({selector: 'needs-named-tpl', template: ''}) class NeedsNamedTpl { - @ViewChild('tpl') viewTpl: TemplateRef; - @ContentChild('tpl') contentTpl: TemplateRef; + @ViewChild('tpl') viewTpl: TemplateRef; + @ContentChild('tpl') contentTpl: TemplateRef; constructor(public vc: ViewContainerRef) {} } @@ -1078,7 +1080,7 @@ class NeedsViewChildWithRead { class NeedsViewContainerWithRead { @ViewChild('q', {read: ViewContainerRef}) vc: ViewContainerRef; @ViewChild('nonExisting', {read: ViewContainerRef}) nonExistingVar: ViewContainerRef; - @ContentChild(TemplateRef) template: TemplateRef; + @ContentChild(TemplateRef) template: TemplateRef; createView() { this.vc.createEmbeddedView(this.template); } } diff --git a/modules/angular2/test/core/linker/view_injector_integration_spec.ts b/modules/angular2/test/core/linker/view_injector_integration_spec.ts index 7ae2ff2b3d..8cb06951bb 100644 --- a/modules/angular2/test/core/linker/view_injector_integration_spec.ts +++ b/modules/angular2/test/core/linker/view_injector_integration_spec.ts @@ -206,13 +206,13 @@ class NeedsViewContainerRef { @Directive({selector: '[needsTemplateRef]'}) class NeedsTemplateRef { templateRef; - constructor(ref: TemplateRef) { this.templateRef = ref; } + constructor(ref: TemplateRef) { this.templateRef = ref; } } @Directive({selector: '[optionallyNeedsTemplateRef]'}) class OptionallyNeedsTemplateRef { templateRef; - constructor(@Optional() ref: TemplateRef) { this.templateRef = ref; } + constructor(@Optional() ref: TemplateRef) { this.templateRef = ref; } } @Directive({selector: '[directiveNeedsChangeDetectorRef]'}) diff --git a/tools/public_api_guard/public_api_spec.ts b/tools/public_api_guard/public_api_spec.ts index 1c622ad797..b1fc119a92 100644 --- a/tools/public_api_guard/public_api_spec.ts +++ b/tools/public_api_guard/public_api_spec.ts @@ -112,15 +112,15 @@ const CORE = [ 'DebugNode', 'DebugNode.componentInstance:any', 'DebugNode.constructor(nativeNode:any, parent:DebugNode, _debugInfo:RenderDebugInfo)', - 'DebugNode.getLocal(name:string):any', 'DebugNode.inject(token:any):any', 'DebugNode.injector:Injector', 'DebugNode.listeners:EventListener[]', - 'DebugNode.locals:{[key:string]:any}', 'DebugNode.nativeNode:any', 'DebugNode.parent:DebugElement', 'DebugNode.providerTokens:any[]', 'DebugNode.source:string', + 'DebugNode.context:any', + 'DebugNode.references:{[key:string]:any}', 'DebugElement', 'DebugElement.children:DebugElement[]', 'DebugElement.nativeElement:any', @@ -164,10 +164,9 @@ const CORE = [ 'ElementRef', 'ElementRef.nativeElement:any', 'ElementRef.constructor(nativeElement:any)', - 'EmbeddedViewRef', - 'EmbeddedViewRef.hasLocal(variableName:string):boolean', + 'EmbeddedViewRef', + 'EmbeddedViewRef.context:C', 'EmbeddedViewRef.rootNodes:any[]', - 'EmbeddedViewRef.setLocal(variableName:string, value:any):void', 'EmbeddedViewRef.destroy():any', 'EventEmitter.constructor(isAsync:boolean)', 'EventEmitter.emit(value:T):any', @@ -415,9 +414,9 @@ const CORE = [ 'SkipSelfMetadataFactory', 'SkipSelfMetadata', 'SkipSelfMetadata.toString():string', - 'TemplateRef', + 'TemplateRef', 'TemplateRef.elementRef:ElementRef', - 'TemplateRef.createEmbeddedView():EmbeddedViewRef', + 'TemplateRef.createEmbeddedView(context:C):EmbeddedViewRef', 'Testability', 'Testability.constructor(_ngZone:NgZone)', 'Testability.decreasePendingRequestCount():number', @@ -446,7 +445,7 @@ const CORE = [ 'ViewChildrenMetadata.constructor(_selector:Type|string, {read=null}:{read?:any})', 'ViewContainerRef', 'ViewContainerRef.clear():void', - 'ViewContainerRef.createEmbeddedView(templateRef:TemplateRef, index:number):EmbeddedViewRef', + 'ViewContainerRef.createEmbeddedView(templateRef:TemplateRef, context:any, index:number):EmbeddedViewRef', 'ViewContainerRef.createComponent(componentFactory:ComponentFactory, index:number, injector:Injector, projectableNodes:any[][]):ComponentRef', 'ViewContainerRef.detach(index:number):ViewRef', 'ViewContainerRef.element:ElementRef', @@ -692,10 +691,10 @@ const COMMON = [ 'NgControlStatus.ngClassUntouched:boolean', 'NgControlStatus.ngClassValid:boolean', 'NgFor', - 'NgFor.constructor(_viewContainer:ViewContainerRef, _templateRef:TemplateRef, _iterableDiffers:IterableDiffers, _cdr:ChangeDetectorRef)', + 'NgFor.constructor(_viewContainer:ViewContainerRef, _templateRef:TemplateRef, _iterableDiffers:IterableDiffers, _cdr:ChangeDetectorRef)', 'NgFor.ngDoCheck():any', 'NgFor.ngForOf=(value:any)', - 'NgFor.ngForTemplate=(value:TemplateRef)', + 'NgFor.ngForTemplate=(value:TemplateRef)', 'NgFor.ngForTrackBy=(value:TrackByFn)', 'NgForm', 'NgForm.addControl(dir:NgControl):void', @@ -743,11 +742,11 @@ const COMMON = [ 'NgFormModel.removeControlGroup(dir:NgControlGroup):any', 'NgFormModel.updateModel(dir:NgControl, value:any):void', 'NgIf', - 'NgIf.constructor(_viewContainer:ViewContainerRef, _templateRef:TemplateRef)', + 'NgIf.constructor(_viewContainer:ViewContainerRef, _templateRef:TemplateRef)', 'NgIf.ngIf=(newCondition:any)', 'NgTemplateOutlet', 'NgTemplateOutlet.constructor(_viewContainerRef:ViewContainerRef)', - 'NgTemplateOutlet.ngTemplateOutlet=(templateRef:TemplateRef)', + 'NgTemplateOutlet.ngTemplateOutlet=(templateRef:TemplateRef)', 'NgLocalization', 'NgLocalization.getPluralCategory(value:any):string', 'NgModel', @@ -765,7 +764,7 @@ const COMMON = [ 'NgPlural.cases:QueryList', 'NgPlural.constructor(_localization:NgLocalization)', 'NgPlural.ngAfterContentInit():any', - 'NgPluralCase.constructor(value:string, template:TemplateRef, viewContainer:ViewContainerRef)', + 'NgPluralCase.constructor(value:string, template:TemplateRef, viewContainer:ViewContainerRef)', 'NgPlural.ngPlural=(value:number)', 'NgPluralCase', 'NgSelectOption', @@ -781,9 +780,9 @@ const COMMON = [ 'NgSwitch', 'NgSwitch.ngSwitch=(value:any)', 'NgSwitchDefault', - 'NgSwitchDefault.constructor(viewContainer:ViewContainerRef, templateRef:TemplateRef, sswitch:NgSwitch)', + 'NgSwitchDefault.constructor(viewContainer:ViewContainerRef, templateRef:TemplateRef, sswitch:NgSwitch)', 'NgSwitchWhen', - 'NgSwitchWhen.constructor(viewContainer:ViewContainerRef, templateRef:TemplateRef, ngSwitch:NgSwitch)', + 'NgSwitchWhen.constructor(viewContainer:ViewContainerRef, templateRef:TemplateRef, ngSwitch:NgSwitch)', 'NgSwitchWhen.ngSwitchWhen=(value:any)', 'NumberPipe', 'PatternValidator',