From efbd446d18e6e0380beafcad6e94a7751d788623 Mon Sep 17 00:00:00 2001 From: Tobias Bosch Date: Mon, 18 Apr 2016 13:24:42 -0700 Subject: [PATCH] refactor(core): add `Query.read` and remove `DynamicComponentLoader.loadIntoLocation`. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds the feature for `@ViewChild`/`@ViewChildren`/`@ContentChild`/`@ContentChildren` to define what to read from the queried element. E.g. `@ViewChild(`someVar`, read: ViewContainerRef)` will locate the element with a variable `someVar` on it and return a `ViewContainerRef` for it. Background: With this change, Angular knows exactly at which elements there will be `ViewConainerRef`s as the user has to ask explicitly of them. This simplifies codegen and will make converting Angular templates into server side templates simpler as well. BREAKING CHANGE: - `DynamicComponentLoader.loadIntoLocation` has been removed. Use `@ViewChild(‘myVar’, read: ViewContainerRef)` to get hold of a `ViewContainerRef` at an element with variable `myVar`. - `DynamicComponentLoader.loadNextToLocation` now takes a `ViewContainerRef` instead of an `ElementRef`. - `AppViewManager` is renamed into `ViewUtils` and is a mere private utility service. --- .../angular2/src/compiler/compile_metadata.ts | 20 +- modules/angular2/src/compiler/identifiers.ts | 12 +- .../angular2/src/compiler/provider_parser.ts | 70 ++-- .../angular2/src/compiler/runtime_compiler.ts | 4 +- .../angular2/src/compiler/runtime_metadata.ts | 3 +- modules/angular2/src/compiler/template_ast.ts | 9 +- .../angular2/src/compiler/template_parser.ts | 20 +- .../compiler/view_compiler/compile_element.ts | 153 ++++---- .../compiler/view_compiler/compile_query.ts | 2 +- .../compiler/view_compiler/compile_view.ts | 2 +- .../src/compiler/view_compiler/constants.ts | 4 +- .../compiler/view_compiler/event_binder.ts | 7 +- .../compiler/view_compiler/property_binder.ts | 3 +- .../compiler/view_compiler/view_builder.ts | 76 ++-- .../src/core/application_common_providers.ts | 5 +- modules/angular2/src/core/linker.ts | 1 - .../src/core/linker/component_factory.ts | 22 +- .../core/linker/dynamic_component_loader.ts | 82 +--- modules/angular2/src/core/linker/element.ts | 23 +- .../angular2/src/core/linker/element_ref.ts | 14 +- .../angular2/src/core/linker/template_ref.ts | 6 +- modules/angular2/src/core/linker/view.ts | 15 +- .../src/core/linker/view_container_ref.ts | 9 +- .../angular2/src/core/linker/view_manager.ts | 77 ---- .../angular2/src/core/linker/view_utils.ts | 26 ++ modules/angular2/src/core/metadata.dart | 19 +- modules/angular2/src/core/metadata.ts | 23 +- modules/angular2/src/core/metadata/di.ts | 30 +- .../directives/router_link_transform.ts | 4 +- .../src/router/directives/router_outlet.ts | 6 +- modules/angular2/src/upgrade/constants.ts | 1 - .../src/upgrade/downgrade_ng2_adapter.ts | 4 +- .../angular2/src/upgrade/upgrade_adapter.ts | 13 +- .../test/compiler/template_parser_spec.ts | 6 +- .../linker/dynamic_component_loader_spec.ts | 350 +++++------------- .../core/linker/query_integration_spec.ts | 141 ++++++- .../linker/view_injector_integration_spec.ts | 2 +- modules/angular2/test/public_api_spec.ts | 1 - .../integration/impl/fixture_components.ts | 12 +- .../worker/renderer_integration_spec.ts | 17 +- modules/benchmarks/src/costs/index.ts | 4 +- tools/public_api_guard/public_api_spec.ts | 27 +- 42 files changed, 608 insertions(+), 717 deletions(-) delete mode 100644 modules/angular2/src/core/linker/view_manager.ts diff --git a/modules/angular2/src/compiler/compile_metadata.ts b/modules/angular2/src/compiler/compile_metadata.ts index 3c8ed69bf6..4be4e5e215 100644 --- a/modules/angular2/src/compiler/compile_metadata.ts +++ b/modules/angular2/src/compiler/compile_metadata.ts @@ -13,7 +13,12 @@ import { isArray } from 'angular2/src/facade/lang'; import {unimplemented, BaseException} from 'angular2/src/facade/exceptions'; -import {StringMapWrapper, MapWrapper, SetWrapper} from 'angular2/src/facade/collection'; +import { + StringMapWrapper, + MapWrapper, + SetWrapper, + ListWrapper +} from 'angular2/src/facade/collection'; import { ChangeDetectionStrategy, CHANGE_DETECTION_STRATEGY_VALUES @@ -414,17 +419,20 @@ export class CompileQueryMetadata { descendants: boolean; first: boolean; propertyName: string; + read: CompileTokenMetadata; - constructor({selectors, descendants, first, propertyName}: { + constructor({selectors, descendants, first, propertyName, read}: { selectors?: Array, descendants?: boolean, first?: boolean, - propertyName?: string + propertyName?: string, + read?: CompileTokenMetadata } = {}) { this.selectors = selectors; this.descendants = normalizeBool(descendants); this.first = normalizeBool(first); this.propertyName = propertyName; + this.read = read; } static fromJson(data: {[key: string]: any}): CompileQueryMetadata { @@ -432,7 +440,8 @@ export class CompileQueryMetadata { selectors: _arrayFromJson(data['selectors'], CompileTokenMetadata.fromJson), descendants: data['descendants'], first: data['first'], - propertyName: data['propertyName'] + propertyName: data['propertyName'], + read: _objFromJson(data['read'], CompileTokenMetadata.fromJson) }); } @@ -441,7 +450,8 @@ export class CompileQueryMetadata { 'selectors': _arrayToJson(this.selectors), 'descendants': this.descendants, 'first': this.first, - 'propertyName': this.propertyName + 'propertyName': this.propertyName, + 'read': _objToJson(this.read) }; } } diff --git a/modules/angular2/src/compiler/identifiers.ts b/modules/angular2/src/compiler/identifiers.ts index f247a37cf5..453ed25ce4 100644 --- a/modules/angular2/src/compiler/identifiers.ts +++ b/modules/angular2/src/compiler/identifiers.ts @@ -2,6 +2,7 @@ import {CompileIdentifierMetadata, CompileTokenMetadata} from './compile_metadat import {AppView} from 'angular2/src/core/linker/view'; import {StaticNodeDebugInfo, DebugContext} from 'angular2/src/core/linker/debug_context'; import { + ViewUtils, flattenNestedViewRenderNodes, interpolate, checkBinding @@ -15,7 +16,6 @@ import { ChangeDetectorState, ChangeDetectionStrategy } from 'angular2/src/core/change_detection/change_detection'; -import {AppViewManager_} from 'angular2/src/core/linker/view_manager'; import {AppElement} from 'angular2/src/core/linker/element'; import {ElementRef} from 'angular2/src/core/linker/element_ref'; import {ViewContainerRef} from 'angular2/src/core/linker/view_container_ref'; @@ -34,7 +34,7 @@ var CD_MODULE_URL = 'asset:angular2/lib/src/core/change_detection/change_detecti // Reassign the imports to different variables so we can // define static variables with the name of the import. // (only needed for Dart). -var impAppViewManager_ = AppViewManager_; +var impViewUtils = ViewUtils; var impAppView = AppView; var impDebugContext = DebugContext; var impAppElement = AppElement; @@ -61,10 +61,10 @@ var impInterpolate = interpolate; var impCheckBinding = checkBinding; export class Identifiers { - static AppViewManager_ = new CompileIdentifierMetadata({ - name: 'AppViewManager_', - moduleUrl: 'asset:angular2/lib/src/core/linker/view_manager' + MODULE_SUFFIX, - runtime: impAppViewManager_ + static ViewUtils = new CompileIdentifierMetadata({ + name: 'ViewUtils', + moduleUrl: 'asset:angular2/lib/src/core/linker/view_utils' + MODULE_SUFFIX, + runtime: impViewUtils }); static AppView = new CompileIdentifierMetadata( {name: 'AppView', moduleUrl: APP_VIEW_MODULE_URL, runtime: impAppView}); diff --git a/modules/angular2/src/compiler/provider_parser.ts b/modules/angular2/src/compiler/provider_parser.ts index 4dc92e918d..5a9788a211 100644 --- a/modules/angular2/src/compiler/provider_parser.ts +++ b/modules/angular2/src/compiler/provider_parser.ts @@ -65,28 +65,42 @@ export class ProviderElementContext { private _seenProviders = new CompileTokenMap(); private _allProviders: CompileTokenMap; private _attrs: {[key: string]: string}; + private _hasViewContainer: boolean = false; constructor(private _viewContext: ProviderViewContext, private _parent: ProviderElementContext, private _isViewRoot: boolean, private _directiveAsts: DirectiveAst[], - attrs: AttrAst[], private _sourceSpan: ParseSourceSpan) { + attrs: AttrAst[], vars: VariableAst[], private _sourceSpan: ParseSourceSpan) { this._attrs = {}; attrs.forEach((attrAst) => this._attrs[attrAst.name] = attrAst.value); var directivesMeta = _directiveAsts.map(directiveAst => directiveAst.directive); this._allProviders = _resolveProvidersFromDirectives(directivesMeta, _sourceSpan, _viewContext.errors); this._contentQueries = _getContentQueries(directivesMeta); + var queriedTokens = new CompileTokenMap(); + this._allProviders.values().forEach( + (provider) => { this._addQueryReadsTo(provider.token, queriedTokens); }); + vars.forEach((varAst) => { + var varToken = new CompileTokenMetadata({value: varAst.name}); + this._addQueryReadsTo(varToken, queriedTokens); + }); + if (isPresent(queriedTokens.get(identifierToken(Identifiers.ViewContainerRef)))) { + this._hasViewContainer = true; + } + // create the providers that we know are eager first this._allProviders.values().forEach((provider) => { - if (provider.eager || this.isQueried(provider.token)) { - this._getLocalProvider(provider.providerType, provider.token, true); + var eager = provider.eager || isPresent(queriedTokens.get(provider.token)); + if (eager) { + this._getOrCreateLocalProvider(provider.providerType, provider.token, true); } }); } afterElement() { // collect lazy providers - this._allProviders.values().forEach( - (provider) => { this._getLocalProvider(provider.providerType, provider.token, false); }); + this._allProviders.values().forEach((provider) => { + this._getOrCreateLocalProvider(provider.providerType, provider.token, false); + }); } get transformProviders(): ProviderAst[] { return this._transformedProviders.values(); } @@ -101,30 +115,42 @@ export class ProviderElementContext { return sortedDirectives; } - private isQueried(token: CompileTokenMetadata): boolean { + get transformedHasViewContainer(): boolean { return this._hasViewContainer; } + + private _addQueryReadsTo(token: CompileTokenMetadata, queryReadTokens: CompileTokenMap) { + this._getQueriesFor(token).forEach((query) => { + var queryReadToken = isPresent(query.read) ? query.read : token; + if (isBlank(queryReadTokens.get(queryReadToken))) { + queryReadTokens.add(queryReadToken, true); + } + }); + } + + private _getQueriesFor(token: CompileTokenMetadata): CompileQueryMetadata[] { + var result: CompileQueryMetadata[] = []; var currentEl: ProviderElementContext = this; var distance = 0; + var queries: CompileQueryMetadata[]; while (currentEl !== null) { - var localQueries = currentEl._contentQueries.get(token); - if (isPresent(localQueries)) { - if (localQueries.some((query) => query.descendants || distance <= 1)) { - return true; - } + queries = currentEl._contentQueries.get(token); + if (isPresent(queries)) { + ListWrapper.addAll(result, queries.filter((query) => query.descendants || distance <= 1)); } if (currentEl._directiveAsts.length > 0) { distance++; } currentEl = currentEl._parent; } - if (isPresent(this._viewContext.viewQueries.get(token))) { - return true; + queries = this._viewContext.viewQueries.get(token); + if (isPresent(queries)) { + ListWrapper.addAll(result, queries); } - return false; + return result; } - private _getLocalProvider(requestingProviderType: ProviderAstType, token: CompileTokenMetadata, - eager: boolean): ProviderAst { + private _getOrCreateLocalProvider(requestingProviderType: ProviderAstType, + token: CompileTokenMetadata, eager: boolean): ProviderAst { var resolvedProvider = this._allProviders.get(token); if (isBlank(resolvedProvider) || ((requestingProviderType === ProviderAstType.Directive || @@ -198,17 +224,19 @@ export class ProviderElementContext { if (dep.token.equalsTo(identifierToken(Identifiers.Renderer)) || dep.token.equalsTo(identifierToken(Identifiers.ElementRef)) || dep.token.equalsTo(identifierToken(Identifiers.ChangeDetectorRef)) || - dep.token.equalsTo(identifierToken(Identifiers.ViewContainerRef)) || dep.token.equalsTo(identifierToken(Identifiers.TemplateRef))) { return dep; } + if (dep.token.equalsTo(identifierToken(Identifiers.ViewContainerRef))) { + this._hasViewContainer = true; + } } // access the injector if (dep.token.equalsTo(identifierToken(Identifiers.Injector))) { return dep; } // access providers - if (isPresent(this._getLocalProvider(requestingProviderType, dep.token, eager))) { + if (isPresent(this._getOrCreateLocalProvider(requestingProviderType, dep.token, eager))) { return dep; } } @@ -393,11 +421,11 @@ function _getContentQueries( function _addQueryToTokenMap(map: CompileTokenMap, query: CompileQueryMetadata) { - query.selectors.forEach((selector) => { - var entry = map.get(selector); + query.selectors.forEach((token: CompileTokenMetadata) => { + var entry = map.get(token); if (isBlank(entry)) { entry = []; - map.add(selector, entry); + map.add(token, entry); } entry.push(query); }); diff --git a/modules/angular2/src/compiler/runtime_compiler.ts b/modules/angular2/src/compiler/runtime_compiler.ts index 299d29b82d..d7c98f3060 100644 --- a/modules/angular2/src/compiler/runtime_compiler.ts +++ b/modules/angular2/src/compiler/runtime_compiler.ts @@ -225,8 +225,8 @@ class CompiledTemplate { viewFactory: Function = null; proxyViewFactory: Function; constructor() { - this.proxyViewFactory = (viewManager, childInjector, contextEl) => - this.viewFactory(viewManager, childInjector, contextEl); + this.proxyViewFactory = (viewUtils, childInjector, contextEl) => + this.viewFactory(viewUtils, childInjector, contextEl); } init(viewFactory: Function) { this.viewFactory = viewFactory; } diff --git a/modules/angular2/src/compiler/runtime_metadata.ts b/modules/angular2/src/compiler/runtime_metadata.ts index afecf4d46d..b066816736 100644 --- a/modules/angular2/src/compiler/runtime_metadata.ts +++ b/modules/angular2/src/compiler/runtime_metadata.ts @@ -295,7 +295,8 @@ export class RuntimeMetadataResolver { selectors: selectors, first: q.first, descendants: q.descendants, - propertyName: propertyName + propertyName: propertyName, + read: isPresent(q.read) ? this.getTokenMetadata(q.read) : null }); } } diff --git a/modules/angular2/src/compiler/template_ast.ts b/modules/angular2/src/compiler/template_ast.ts index d8c3f92899..558956010a 100644 --- a/modules/angular2/src/compiler/template_ast.ts +++ b/modules/angular2/src/compiler/template_ast.ts @@ -98,8 +98,9 @@ export class ElementAst implements TemplateAst { constructor(public name: string, public attrs: AttrAst[], public inputs: BoundElementPropertyAst[], public outputs: BoundEventAst[], public exportAsVars: VariableAst[], public directives: DirectiveAst[], - public providers: ProviderAst[], public children: TemplateAst[], - public ngContentIndex: number, public sourceSpan: ParseSourceSpan) {} + public providers: ProviderAst[], public hasViewContainer: boolean, + public children: TemplateAst[], public ngContentIndex: number, + public sourceSpan: ParseSourceSpan) {} visit(visitor: TemplateAstVisitor, context: any): any { return visitor.visitElement(this, context); @@ -129,8 +130,8 @@ export class ElementAst implements TemplateAst { export class EmbeddedTemplateAst implements TemplateAst { constructor(public attrs: AttrAst[], public outputs: BoundEventAst[], public vars: VariableAst[], public directives: DirectiveAst[], public providers: ProviderAst[], - public children: TemplateAst[], public ngContentIndex: number, - public sourceSpan: ParseSourceSpan) {} + public hasViewContainer: boolean, public children: TemplateAst[], + public ngContentIndex: number, public sourceSpan: ParseSourceSpan) {} visit(visitor: TemplateAstVisitor, context: any): any { return visitor.visitEmbeddedTemplate(this, context); diff --git a/modules/angular2/src/compiler/template_parser.ts b/modules/angular2/src/compiler/template_parser.ts index 0595beedd0..407f0c50af 100644 --- a/modules/angular2/src/compiler/template_parser.ts +++ b/modules/angular2/src/compiler/template_parser.ts @@ -328,7 +328,7 @@ class TemplateParseVisitor implements HtmlAstVisitor { var isViewRoot = parent.isTemplateElement || hasInlineTemplates; var providerContext = new ProviderElementContext(this.providerViewContext, parent.providerContext, isViewRoot, - directiveAsts, attrs, element.sourceSpan); + directiveAsts, attrs, vars, element.sourceSpan); var children = htmlVisitAll( preparsedElement.nonBindable ? NON_BINDABLE_VISITOR : this, element.children, ElementContext.create(isTemplateElement, directiveAsts, @@ -355,10 +355,10 @@ class TemplateParseVisitor implements HtmlAstVisitor { this._assertNoComponentsNorElementBindingsOnTemplate(directiveAsts, elementProps, element.sourceSpan); - parsedElement = - new EmbeddedTemplateAst(attrs, events, vars, providerContext.transformedDirectiveAsts, - providerContext.transformProviders, children, - hasInlineTemplates ? null : ngContentIndex, element.sourceSpan); + parsedElement = new EmbeddedTemplateAst( + attrs, events, vars, providerContext.transformedDirectiveAsts, + providerContext.transformProviders, providerContext.transformedHasViewContainer, children, + hasInlineTemplates ? null : ngContentIndex, element.sourceSpan); } else { this._assertOnlyOneComponent(directiveAsts, element.sourceSpan); var elementExportAsVars = vars.filter(varAst => varAst.value.length === 0); @@ -367,7 +367,8 @@ class TemplateParseVisitor implements HtmlAstVisitor { parsedElement = new ElementAst( nodeName, attrs, elementProps, events, elementExportAsVars, - providerContext.transformedDirectiveAsts, providerContext.transformProviders, children, + providerContext.transformedDirectiveAsts, providerContext.transformProviders, + providerContext.transformedHasViewContainer, children, hasInlineTemplates ? null : ngContentIndex, element.sourceSpan); } if (hasInlineTemplates) { @@ -382,12 +383,13 @@ class TemplateParseVisitor implements HtmlAstVisitor { templateDirectiveAsts, templateElementProps, element.sourceSpan); var templateProviderContext = new ProviderElementContext( this.providerViewContext, parent.providerContext, parent.isTemplateElement, - templateDirectiveAsts, [], element.sourceSpan); + templateDirectiveAsts, [], templateVars, element.sourceSpan); templateProviderContext.afterElement(); parsedElement = new EmbeddedTemplateAst([], [], templateVars, templateProviderContext.transformedDirectiveAsts, templateProviderContext.transformProviders, + templateProviderContext.transformedHasViewContainer, [parsedElement], ngContentIndex, element.sourceSpan); } return parsedElement; @@ -765,8 +767,8 @@ class NonBindableVisitor implements HtmlAstVisitor { var selector = createElementCssSelector(ast.name, attrNameAndValues); var ngContentIndex = parent.findNgContentIndex(selector); var children = htmlVisitAll(this, ast.children, EMPTY_ELEMENT_CONTEXT); - return new ElementAst(ast.name, htmlVisitAll(this, ast.attrs), [], [], [], [], [], children, - ngContentIndex, ast.sourceSpan); + return new ElementAst(ast.name, htmlVisitAll(this, ast.attrs), [], [], [], [], [], false, + children, ngContentIndex, ast.sourceSpan); } visitComment(ast: HtmlCommentAst, context: any): any { return null; } visitAttr(ast: HtmlAttrAst, context: any): AttrAst { diff --git a/modules/angular2/src/compiler/view_compiler/compile_element.ts b/modules/angular2/src/compiler/view_compiler/compile_element.ts index c1f5ad32d5..6c5b0446d5 100644 --- a/modules/angular2/src/compiler/view_compiler/compile_element.ts +++ b/modules/angular2/src/compiler/view_compiler/compile_element.ts @@ -30,13 +30,13 @@ export class CompileNode { export class CompileElement extends CompileNode { static createNull(): CompileElement { - return new CompileElement(null, null, null, null, null, [], [], {}); + return new CompileElement(null, null, null, null, null, null, [], [], false, false, {}); } private _compViewExpr: o.Expression = null; - public component: CompileDirectiveMetadata = null; - private _appElement: o.Expression; - private _defaultInjector: o.Expression; + public appElement: o.ReadPropExpr; + public elementRef: o.Expression; + public injector: o.Expression; private _instances = new CompileTokenMap(); private _resolvedProviders: CompileTokenMap; @@ -50,17 +50,45 @@ export class CompileElement extends CompileNode { constructor(parent: CompileElement, view: CompileView, nodeIndex: number, renderNode: o.Expression, sourceAst: TemplateAst, + public component: CompileDirectiveMetadata, private _directives: CompileDirectiveMetadata[], - private _resolvedProvidersArray: ProviderAst[], + private _resolvedProvidersArray: ProviderAst[], public hasViewContainer: boolean, + public hasEmbeddedView: boolean, public variableTokens: {[key: string]: CompileTokenMetadata}) { super(parent, view, nodeIndex, renderNode, sourceAst); + this.elementRef = o.importExpr(Identifiers.ElementRef).instantiate([this.renderNode]); + this._instances.add(identifierToken(Identifiers.ElementRef), this.elementRef); + this.injector = o.THIS_EXPR.callMethod('injector', [o.literal(this.nodeIndex)]); + this._instances.add(identifierToken(Identifiers.Injector), this.injector); + this._instances.add(identifierToken(Identifiers.Renderer), o.THIS_EXPR.prop('renderer')); + if (this.hasViewContainer || this.hasEmbeddedView || isPresent(this.component)) { + this._createAppElement(); + } } - setComponent(component: CompileDirectiveMetadata, compViewExpr: o.Expression) { - this.component = component; + private _createAppElement() { + var fieldName = `_appEl_${this.nodeIndex}`; + var parentNodeIndex = this.isRootElement() ? null : this.parent.nodeIndex; + this.view.fields.push(new o.ClassField(fieldName, o.importType(Identifiers.AppElement), + [o.StmtModifier.Private])); + var statement = o.THIS_EXPR.prop(fieldName) + .set(o.importExpr(Identifiers.AppElement) + .instantiate([ + o.literal(this.nodeIndex), + o.literal(parentNodeIndex), + o.THIS_EXPR, + this.renderNode + ])) + .toStmt(); + this.view.createMethod.addStmt(statement); + this.appElement = o.THIS_EXPR.prop(fieldName); + this._instances.add(identifierToken(Identifiers.AppElement), this.appElement); + } + + setComponentView(compViewExpr: o.Expression) { this._compViewExpr = compViewExpr; this.contentNodesByNgContentIndex = - ListWrapper.createFixedSize(component.template.ngContentSelectors.length); + ListWrapper.createFixedSize(this.component.template.ngContentSelectors.length); for (var i = 0; i < this.contentNodesByNgContentIndex.length; i++) { this.contentNodesByNgContentIndex[i] = []; } @@ -71,7 +99,7 @@ export class CompileElement extends CompileNode { if (isPresent(embeddedView)) { var createTemplateRefExpr = o.importExpr(Identifiers.TemplateRef_) - .instantiate([this.getOrCreateAppElement(), this.embeddedView.viewFactory]); + .instantiate([this.appElement, this.embeddedView.viewFactory]); var provider = new CompileProviderMetadata( {token: identifierToken(Identifiers.TemplateRef), useValue: createTemplateRefExpr}); // Add TemplateRef as first provider as it does not have deps on other providers @@ -82,6 +110,11 @@ export class CompileElement extends CompileNode { } beforeChildren(): void { + if (this.hasViewContainer) { + this._instances.add(identifierToken(Identifiers.ViewContainerRef), + this.appElement.prop('vcRef')); + } + this._resolvedProviders = new CompileTokenMap(); this._resolvedProvidersArray.forEach(provider => this._resolvedProviders.add(provider.token, provider)); @@ -127,36 +160,54 @@ export class CompileElement extends CompileNode { var directive = this._directives[i]; directive.queries.forEach((queryMeta) => { this._addQuery(queryMeta, directiveInstance); }); } + var queriesWithReads: _QueryWithRead[] = []; this._resolvedProviders.values().forEach((resolvedProvider) => { var queriesForProvider = this._getQueriesFor(resolvedProvider.token); - var providerExpr = this._instances.get(resolvedProvider.token); - queriesForProvider.forEach((query) => { query.addValue(providerExpr, this.view); }); + ListWrapper.addAll( + queriesWithReads, + queriesForProvider.map(query => new _QueryWithRead(query, resolvedProvider.token))); }); StringMapWrapper.forEach(this.variableTokens, (_, varName) => { var token = this.variableTokens[varName]; var varValue; - var varValueForQuery; if (isPresent(token)) { - varValue = varValueForQuery = this._instances.get(token); + varValue = this._instances.get(token); } else { - varValueForQuery = this.getOrCreateAppElement().prop('ref'); varValue = this.renderNode; } this.view.variables.set(varName, varValue); - this.view.namedAppElements.push([varName, this.getOrCreateAppElement()]); - - var queriesForProvider = this._getQueriesFor(new CompileTokenMetadata({value: varName})); - queriesForProvider.forEach((query) => { query.addValue(varValueForQuery, this.view); }); + var varToken = new CompileTokenMetadata({value: varName}); + ListWrapper.addAll(queriesWithReads, this._getQueriesFor(varToken) + .map(query => new _QueryWithRead(query, varToken))); }); + queriesWithReads.forEach((queryWithRead) => { + var value: o.Expression; + if (isPresent(queryWithRead.read.identifier)) { + // query for an identifier + value = this._instances.get(queryWithRead.read); + } else { + // query for a variable + var token = this.variableTokens[queryWithRead.read.value]; + if (isPresent(token)) { + value = this._instances.get(token); + } else { + value = this.elementRef; + } + } + if (isPresent(value)) { + queryWithRead.query.addValue(value, this.view); + } + }); + if (isPresent(this.component)) { var componentConstructorViewQueryList = isPresent(this.component) ? o.literalArr(this._componentConstructorViewQueryLists) : o.NULL_EXPR; var compExpr = isPresent(this.getComponent()) ? this.getComponent() : o.NULL_EXPR; this.view.createMethod.addStmt( - this.getOrCreateAppElement() - .callMethod('initComponent', - [compExpr, componentConstructorViewQueryList, this._compViewExpr]) + this.appElement.callMethod( + 'initComponent', + [compExpr, componentConstructorViewQueryList, this._compViewExpr]) .toStmt()); } } @@ -202,43 +253,6 @@ export class CompileElement extends CompileNode { return res; } - getOptionalAppElement(): o.Expression { return this._appElement; } - - getOrCreateAppElement(): o.Expression { - if (isBlank(this._appElement)) { - var parentNodeIndex = this.isRootElement() ? null : this.parent.nodeIndex; - var fieldName = `_appEl_${this.nodeIndex}`; - this.view.fields.push(new o.ClassField(fieldName, o.importType(Identifiers.AppElement), - [o.StmtModifier.Private])); - var statement = o.THIS_EXPR.prop(fieldName) - .set(o.importExpr(Identifiers.AppElement) - .instantiate([ - o.literal(this.nodeIndex), - o.literal(parentNodeIndex), - o.THIS_EXPR, - this.renderNode - ])) - .toStmt(); - this.view.createMethod.addStmt(statement); - this._appElement = o.THIS_EXPR.prop(fieldName); - } - return this._appElement; - } - - getOrCreateInjector(): o.Expression { - if (isBlank(this._defaultInjector)) { - var fieldName = `_inj_${this.nodeIndex}`; - this.view.fields.push(new o.ClassField(fieldName, o.importType(Identifiers.Injector), - [o.StmtModifier.Private])); - var statement = o.THIS_EXPR.prop(fieldName) - .set(o.THIS_EXPR.callMethod('injector', [o.literal(this.nodeIndex)])) - .toStmt(); - this.view.createMethod.addStmt(statement); - this._defaultInjector = o.THIS_EXPR.prop(fieldName); - } - return this._defaultInjector; - } - private _getQueriesFor(token: CompileTokenMetadata): CompileQuery[] { var result: CompileQuery[] = []; var currentEl: CompileElement = this; @@ -289,30 +303,20 @@ export class CompileElement extends CompileNode { } if (isPresent(dep.token)) { - // access builtins + // access builtins with special visibility if (isBlank(result)) { - if (dep.token.equalsTo(identifierToken(Identifiers.Renderer))) { - result = o.THIS_EXPR.prop('renderer'); - } else if (dep.token.equalsTo(identifierToken(Identifiers.ElementRef))) { - result = this.getOrCreateAppElement().prop('ref'); - } else if (dep.token.equalsTo(identifierToken(Identifiers.ChangeDetectorRef))) { + if (dep.token.equalsTo(identifierToken(Identifiers.ChangeDetectorRef))) { if (requestingProviderType === ProviderAstType.Component) { return this._compViewExpr.prop('ref'); } else { return o.THIS_EXPR.prop('ref'); } - } else if (dep.token.equalsTo(identifierToken(Identifiers.ViewContainerRef))) { - result = this.getOrCreateAppElement().prop('vcRef'); } } - // access providers + // access regular providers on the element if (isBlank(result)) { result = this._instances.get(dep.token); } - // access the injector - if (isBlank(result) && dep.token.equalsTo(identifierToken(Identifiers.Injector))) { - result = this.getOrCreateInjector(); - } } return result; } @@ -400,3 +404,10 @@ function createProviderProperty(propName: string, provider: ProviderAst, } return o.THIS_EXPR.prop(propName); } + +class _QueryWithRead { + public read: CompileTokenMetadata; + constructor(public query: CompileQuery, match: CompileTokenMetadata) { + this.read = isPresent(query.meta.read) ? query.meta.read : match; + } +} diff --git a/modules/angular2/src/compiler/view_compiler/compile_query.ts b/modules/angular2/src/compiler/view_compiler/compile_query.ts index 22f920d9d3..64c8b40c52 100644 --- a/modules/angular2/src/compiler/view_compiler/compile_query.ts +++ b/modules/angular2/src/compiler/view_compiler/compile_query.ts @@ -77,7 +77,7 @@ export class CompileQuery { function createQueryValues(viewValues: ViewQueryValues): o.Expression[] { return ListWrapper.flatten(viewValues.values.map((entry) => { if (entry instanceof ViewQueryValues) { - return mapNestedViews(entry.view.declarationElement.getOrCreateAppElement(), entry.view, + return mapNestedViews(entry.view.declarationElement.appElement, entry.view, createQueryValues(entry)); } else { return entry; diff --git a/modules/angular2/src/compiler/view_compiler/compile_view.ts b/modules/angular2/src/compiler/view_compiler/compile_view.ts index 36d3ad58be..9d7a8b22a2 100644 --- a/modules/angular2/src/compiler/view_compiler/compile_view.ts +++ b/modules/angular2/src/compiler/view_compiler/compile_view.ts @@ -33,9 +33,9 @@ export class CompilePipe { export class CompileView implements NameResolver { public viewType: ViewType; public viewQueries: CompileTokenMap; - public namedAppElements: Array> = []; public nodes: CompileNode[] = []; + // root nodes or AppElements for ViewContainers public rootNodesOrAppElements: o.Expression[] = []; public bindings: CompileBinding[] = []; diff --git a/modules/angular2/src/compiler/view_compiler/constants.ts b/modules/angular2/src/compiler/view_compiler/constants.ts index 596fd7f095..3f752dbfc7 100644 --- a/modules/angular2/src/compiler/view_compiler/constants.ts +++ b/modules/angular2/src/compiler/view_compiler/constants.ts @@ -59,7 +59,7 @@ export class ChangeDetectionStrategyEnum { } export class ViewConstructorVars { - static viewManager = o.variable('viewManager'); + static viewUtils = o.variable('viewUtils'); static parentInjector = o.variable('parentInjector'); static declarationEl = o.variable('declarationEl'); } @@ -67,7 +67,7 @@ export class ViewConstructorVars { export class ViewProperties { static renderer = o.THIS_EXPR.prop('renderer'); static projectableNodes = o.THIS_EXPR.prop('projectableNodes'); - static viewManager = o.THIS_EXPR.prop('viewManager'); + static viewUtils = o.THIS_EXPR.prop('viewUtils'); } export class EventHandlerVars { static event = o.variable('$event'); } diff --git a/modules/angular2/src/compiler/view_compiler/event_binder.ts b/modules/angular2/src/compiler/view_compiler/event_binder.ts index 3f59de70bf..dd04020467 100644 --- a/modules/angular2/src/compiler/view_compiler/event_binder.ts +++ b/modules/angular2/src/compiler/view_compiler/event_binder.ts @@ -67,10 +67,9 @@ export class CompileEventListener { } finishMethod() { - var markPathToRootStart = - this._hasComponentHostListener ? - this.compileElement.getOrCreateAppElement().prop('componentView') : - o.THIS_EXPR; + var markPathToRootStart = this._hasComponentHostListener ? + this.compileElement.appElement.prop('componentView') : + o.THIS_EXPR; var resultExpr: o.Expression = o.literal(true); this._actionResultExprs.forEach((expr) => { resultExpr = resultExpr.and(expr); }); var stmts = diff --git a/modules/angular2/src/compiler/view_compiler/property_binder.ts b/modules/angular2/src/compiler/view_compiler/property_binder.ts index 8184ee2853..9b1da586ed 100644 --- a/modules/angular2/src/compiler/view_compiler/property_binder.ts +++ b/modules/angular2/src/compiler/view_compiler/property_binder.ts @@ -189,8 +189,7 @@ export function bindDirectiveInputs(directiveAst: DirectiveAst, directiveInstanc }); if (isOnPushComp) { detectChangesInInputsMethod.addStmt(new o.IfStmt(DetectChangesVars.changed, [ - compileElement.getOrCreateAppElement() - .prop('componentView') + compileElement.appElement.prop('componentView') .callMethod('markAsCheckOnce', []) .toStmt() ])); diff --git a/modules/angular2/src/compiler/view_compiler/view_builder.ts b/modules/angular2/src/compiler/view_compiler/view_builder.ts index 253a28f9c7..275591f77d 100644 --- a/modules/angular2/src/compiler/view_compiler/view_builder.ts +++ b/modules/angular2/src/compiler/view_compiler/view_builder.ts @@ -92,14 +92,15 @@ class ViewBuilderVisitor implements TemplateAstVisitor { private _addRootNodeAndProject(node: CompileNode, ngContentIndex: number, parent: CompileElement) { - var appEl = node instanceof CompileElement ? node.getOptionalAppElement() : null; + var vcAppEl = + (node instanceof CompileElement && node.hasViewContainer) ? node.appElement : null; if (this._isRootNode(parent)) { - // store root nodes only for embedded/host views + // store appElement as root node only for ViewContainers if (this.view.viewType !== ViewType.COMPONENT) { - this.view.rootNodesOrAppElements.push(isPresent(appEl) ? appEl : node.renderNode); + this.view.rootNodesOrAppElements.push(isPresent(vcAppEl) ? vcAppEl : node.renderNode); } } else if (isPresent(parent.component) && isPresent(ngContentIndex)) { - parent.addContentNode(ngContentIndex, isPresent(appEl) ? appEl : node.renderNode); + parent.addContentNode(ngContentIndex, isPresent(vcAppEl) ? vcAppEl : node.renderNode); } } @@ -196,7 +197,7 @@ class ViewBuilderVisitor implements TemplateAstVisitor { this.view.fields.push( new o.ClassField(fieldName, o.importType(this.view.genConfig.renderTypes.renderElement), [o.StmtModifier.Private])); - var createRenderNode = o.THIS_EXPR.prop(fieldName).set(createRenderNodeExpr).toStmt(); + this.view.createMethod.addStmt(o.THIS_EXPR.prop(fieldName).set(createRenderNodeExpr).toStmt()); var renderNode = o.THIS_EXPR.prop(fieldName); @@ -204,7 +205,6 @@ class ViewBuilderVisitor implements TemplateAstVisitor { var directives = ast.directives.map(directiveAst => directiveAst.directive); var variables = _readHtmlAndDirectiveVariables(ast.exportAsVars, ast.directives, this.view.viewType); - this.view.createMethod.addStmt(createRenderNode); var htmlAttrs = _readHtmlAttrs(ast.attrs); var attrNameAndValues = _mergeHtmlAndDirectiveAttrs(htmlAttrs, directives); for (var i = 0; i < attrNameAndValues.length; i++) { @@ -216,8 +216,9 @@ class ViewBuilderVisitor implements TemplateAstVisitor { [renderNode, o.literal(attrName), o.literal(attrValue)]) .toStmt()); } - var compileElement = new CompileElement(parent, this.view, nodeIndex, renderNode, ast, - directives, ast.providers, variables); + var compileElement = + new CompileElement(parent, this.view, nodeIndex, renderNode, ast, component, directives, + ast.providers, ast.hasViewContainer, false, variables); this.view.nodes.push(compileElement); var compViewExpr: o.ReadVarExpr = null; if (isPresent(component)) { @@ -225,14 +226,14 @@ class ViewBuilderVisitor implements TemplateAstVisitor { new CompileIdentifierMetadata({name: getViewFactoryName(component, 0)}); this.targetDependencies.push(new ViewCompileDependency(component, nestedComponentIdentifier)); compViewExpr = o.variable(`compView_${nodeIndex}`); + compileElement.setComponentView(compViewExpr); this.view.createMethod.addStmt(compViewExpr.set(o.importExpr(nestedComponentIdentifier) .callFn([ - ViewProperties.viewManager, - compileElement.getOrCreateInjector(), - compileElement.getOrCreateAppElement() + ViewProperties.viewUtils, + compileElement.injector, + compileElement.appElement ])) .toDeclStmt()); - compileElement.setComponent(component, compViewExpr); } compileElement.beforeChildren(); this._addRootNodeAndProject(compileElement, ast.ngContentIndex, parent); @@ -259,24 +260,25 @@ class ViewBuilderVisitor implements TemplateAstVisitor { this.view.fields.push( new o.ClassField(fieldName, o.importType(this.view.genConfig.renderTypes.renderComment), [o.StmtModifier.Private])); - var createRenderNode = o.THIS_EXPR.prop(fieldName) - .set(ViewProperties.renderer.callMethod( - 'createTemplateAnchor', - [ - this._getParentRenderNode(parent), - this.view.createMethod.resetDebugInfoExpr(nodeIndex, ast) - ])) - .toStmt(); + this.view.createMethod.addStmt( + o.THIS_EXPR.prop(fieldName) + .set(ViewProperties.renderer.callMethod( + 'createTemplateAnchor', + [ + this._getParentRenderNode(parent), + this.view.createMethod.resetDebugInfoExpr(nodeIndex, ast) + ])) + .toStmt()); var renderNode = o.THIS_EXPR.prop(fieldName); var templateVariableBindings = ast.vars.map( varAst => [varAst.value.length > 0 ? varAst.value : IMPLICIT_TEMPLATE_VAR, varAst.name]); var directives = ast.directives.map(directiveAst => directiveAst.directive); - var compileElement = new CompileElement(parent, this.view, nodeIndex, renderNode, ast, - directives, ast.providers, {}); + var compileElement = + new CompileElement(parent, this.view, nodeIndex, renderNode, ast, null, directives, + ast.providers, ast.hasViewContainer, true, {}); this.view.nodes.push(compileElement); - this.view.createMethod.addStmt(createRenderNode); this.nestedViewCount++; var embeddedView = new CompileView( @@ -413,7 +415,7 @@ function createViewClass(view: CompileView, renderCompTypeVar: o.ReadVarExpr, var emptyTemplateVariableBindings = view.templateVariableBindings.map((entry) => [entry[0], o.NULL_EXPR]); var viewConstructorArgs = [ - new o.FnParam(ViewConstructorVars.viewManager.name, o.importType(Identifiers.AppViewManager_)), + new o.FnParam(ViewConstructorVars.viewUtils.name, o.importType(Identifiers.ViewUtils)), new o.FnParam(ViewConstructorVars.parentInjector.name, o.importType(Identifiers.Injector)), new o.FnParam(ViewConstructorVars.declarationEl.name, o.importType(Identifiers.AppElement)) ]; @@ -423,7 +425,7 @@ function createViewClass(view: CompileView, renderCompTypeVar: o.ReadVarExpr, renderCompTypeVar, ViewTypeEnum.fromValue(view.viewType), o.literalMap(emptyTemplateVariableBindings), - ViewConstructorVars.viewManager, + ViewConstructorVars.viewUtils, ViewConstructorVars.parentInjector, ViewConstructorVars.declarationEl, ChangeDetectionStrategyEnum.fromValue(getChangeDetectionMode(view)), @@ -462,7 +464,7 @@ function createViewClass(view: CompileView, renderCompTypeVar: o.ReadVarExpr, function createViewFactory(view: CompileView, viewClass: o.ClassStmt, renderCompTypeVar: o.ReadVarExpr): o.Statement { var viewFactoryArgs = [ - new o.FnParam(ViewConstructorVars.viewManager.name, o.importType(Identifiers.AppViewManager_)), + new o.FnParam(ViewConstructorVars.viewUtils.name, o.importType(Identifiers.ViewUtils)), new o.FnParam(ViewConstructorVars.parentInjector.name, o.importType(Identifiers.Injector)), new o.FnParam(ViewConstructorVars.declarationEl.name, o.importType(Identifiers.AppElement)) ]; @@ -478,15 +480,16 @@ function createViewFactory(view: CompileView, viewClass: o.ClassStmt, initRenderCompTypeStmts = [ new o.IfStmt(renderCompTypeVar.identical(o.NULL_EXPR), [ - renderCompTypeVar.set(ViewConstructorVars.viewManager - .callMethod('createRenderComponentType', - [ - o.literal(templateUrlInfo), - o.literal( - view.component.template.ngContentSelectors.length), - ViewEncapsulationEnum.fromValue(view.component.template.encapsulation), - view.styles - ])) + renderCompTypeVar.set(ViewConstructorVars + .viewUtils.callMethod('createRenderComponentType', + [ + o.literal(templateUrlInfo), + o.literal(view.component + .template.ngContentSelectors.length), + ViewEncapsulationEnum + .fromValue(view.component.template.encapsulation), + view.styles + ])) .toStmt() ]) ]; @@ -513,7 +516,7 @@ function generateCreateMethod(view: CompileView): o.Statement[] { } var resultExpr: o.Expression; if (view.viewType === ViewType.HOST) { - resultExpr = (view.nodes[0]).getOrCreateAppElement(); + resultExpr = (view.nodes[0]).appElement; } else { resultExpr = o.NULL_EXPR; } @@ -523,7 +526,6 @@ function generateCreateMethod(view: CompileView): o.Statement[] { [ createFlatArray(view.rootNodesOrAppElements), o.literalArr(view.nodes.map(node => node.renderNode)), - o.literalMap(view.namedAppElements), o.literalArr(view.disposables), o.literalArr(view.subscriptions) ]) diff --git a/modules/angular2/src/core/application_common_providers.ts b/modules/angular2/src/core/application_common_providers.ts index 0785bfaa23..df0f8b7711 100644 --- a/modules/angular2/src/core/application_common_providers.ts +++ b/modules/angular2/src/core/application_common_providers.ts @@ -11,8 +11,7 @@ import { KeyValueDiffers, defaultKeyValueDiffers } from './change_detection/change_detection'; -import {AppViewManager} from './linker/view_manager'; -import {AppViewManager_} from "./linker/view_manager"; +import {ViewUtils} from "./linker/view_utils"; import {ComponentResolver} from './linker/component_resolver'; import {ReflectorComponentResolver} from "./linker/component_resolver"; import {DynamicComponentLoader} from './linker/dynamic_component_loader'; @@ -27,7 +26,7 @@ var __unused: Type; // avoid unused import when Type union types are erased export const APPLICATION_COMMON_PROVIDERS: Array = CONST_EXPR([ new Provider(ComponentResolver, {useClass: ReflectorComponentResolver}), APP_ID_RANDOM_PROVIDER, - new Provider(AppViewManager, {useClass: AppViewManager_}), + ViewUtils, new Provider(IterableDiffers, {useValue: defaultIterableDiffers}), new Provider(KeyValueDiffers, {useValue: defaultKeyValueDiffers}), new Provider(DynamicComponentLoader, {useClass: DynamicComponentLoader_}) diff --git a/modules/angular2/src/core/linker.ts b/modules/angular2/src/core/linker.ts index dba50ae7bb..15b2fd4a96 100644 --- a/modules/angular2/src/core/linker.ts +++ b/modules/angular2/src/core/linker.ts @@ -1,6 +1,5 @@ // Public API for compiler export {ComponentResolver} from './linker/component_resolver'; -export {AppViewManager} from './linker/view_manager'; export {QueryList} from './linker/query_list'; export {DynamicComponentLoader} from './linker/dynamic_component_loader'; export {ElementRef} from './linker/element_ref'; diff --git a/modules/angular2/src/core/linker/component_factory.ts b/modules/angular2/src/core/linker/component_factory.ts index 1f2e37632a..d51521eedc 100644 --- a/modules/angular2/src/core/linker/component_factory.ts +++ b/modules/angular2/src/core/linker/component_factory.ts @@ -1,10 +1,10 @@ import {Injector} from 'angular2/src/core/di'; import {Type, CONST, isPresent, isBlank} from 'angular2/src/facade/lang'; import {unimplemented} from 'angular2/src/facade/exceptions'; -import {ElementRef, ElementRef_} from './element_ref'; +import {ElementRef} from './element_ref'; import {ViewRef, ViewRef_} from './view_ref'; import {AppElement} from './element'; -import {AppViewManager} from './view_manager'; +import {ViewUtils} from './view_utils'; import {ChangeDetectorRef} from '../change_detection/change_detection'; /** @@ -38,7 +38,7 @@ export abstract class ComponentRef { /** * The {@link ChangeDetectorRef} of the Component instance. */ - get changeDetectorRef(): ChangeDetectorRef { return unimplemented(); }; + get changeDetectorRef(): ChangeDetectorRef { return unimplemented(); } /** * The component type. @@ -57,15 +57,15 @@ export abstract class ComponentRef { } export class ComponentRef_ extends ComponentRef { - constructor(private _location: AppElement, private _componentType: Type) { super(); } - get location(): ElementRef { return this._location.ref; } - get injector(): Injector { return this._location.injector; } - get instance(): any { return this._location.component; }; - get hostView(): ViewRef { return this._location.parentView.ref; }; + constructor(private _hostElement: AppElement, private _componentType: Type) { super(); } + get location(): ElementRef { return this._hostElement.elementRef; } + get injector(): Injector { return this._hostElement.injector; } + get instance(): any { return this._hostElement.component; }; + get hostView(): ViewRef { return this._hostElement.parentView.ref; }; get changeDetectorRef(): ChangeDetectorRef { return this.hostView; }; get componentType(): Type { return this._componentType; } - destroy(): void { this._location.parentView.destroy(); } + destroy(): void { this._hostElement.parentView.destroy(); } onDestroy(callback: Function): void { this.hostView.onDestroy(callback); } } @@ -81,12 +81,12 @@ export class ComponentFactory { */ create(injector: Injector, projectableNodes: any[][] = null, rootSelectorOrNode: string | any = null): ComponentRef { - var vm: AppViewManager = injector.get(AppViewManager); + var vu: ViewUtils = injector.get(ViewUtils); if (isBlank(projectableNodes)) { projectableNodes = []; } // Note: Host views don't need a declarationAppElement! - var hostView = this._viewFactory(vm, injector, null); + var hostView = this._viewFactory(vu, injector, null); var hostElement = hostView.create(projectableNodes, rootSelectorOrNode); return new ComponentRef_(hostElement, this._componentType); } diff --git a/modules/angular2/src/core/linker/dynamic_component_loader.ts b/modules/angular2/src/core/linker/dynamic_component_loader.ts index 6d048f1a8d..7713f18292 100644 --- a/modules/angular2/src/core/linker/dynamic_component_loader.ts +++ b/modules/angular2/src/core/linker/dynamic_component_loader.ts @@ -1,9 +1,8 @@ import {Key, Injector, ResolvedProvider, Provider, provide, Injectable} from 'angular2/src/core/di'; import {ComponentResolver} from './component_resolver'; import {isType, Type, stringify, isPresent} from 'angular2/src/facade/lang'; -import {AppViewManager} from 'angular2/src/core/linker/view_manager'; -import {ElementRef, ElementRef_} from './element_ref'; import {ComponentRef} from './component_factory'; +import {ViewContainerRef} from './view_container_ref'; /** * Service for instantiating a Component and attaching it to a View at a specified location. @@ -61,60 +60,9 @@ export abstract class DynamicComponentLoader { abstract loadAsRoot(type: Type, overrideSelectorOrNode: string | any, injector: Injector, onDispose?: () => void, projectableNodes?: any[][]): Promise; - /** - * Creates an instance of a Component and attaches it to a View Container located inside of the - * Component View of another Component instance. - * - * The targeted Component Instance is specified via its `hostLocation` {@link ElementRef}. The - * location within the Component View of this Component Instance is specified via `anchorName` - * Template Variable Name. - * - * You can optionally provide `providers` to configure the {@link Injector} provisioned for this - * Component Instance. - * - * Returns a promise for the {@link ComponentRef} representing the newly created Component. - * - * ### Example - * - * ``` - * @Component({ - * selector: 'child-component', - * template: 'Child' - * }) - * class ChildComponent { - * } - * - * @Component({ - * selector: 'my-app', - * template: 'Parent (
)' - * }) - * class MyApp { - * constructor(dcl: DynamicComponentLoader, elementRef: ElementRef) { - * dcl.loadIntoLocation(ChildComponent, elementRef, 'child'); - * } - * } - * - * bootstrap(MyApp); - * ``` - * - * Resulting DOM: - * - * ``` - * - * Parent ( - *
- * Child - * ) - *
- * ``` - */ - abstract loadIntoLocation(type: Type, hostLocation: ElementRef, anchorName: string, - providers?: ResolvedProvider[], - projectableNodes?: any[][]): Promise; - /** * Creates an instance of a Component and attaches it to the View Container found at the - * `location` specified as {@link ElementRef}. + * `location` specified as {@link ViewContainerRef}. * * You can optionally provide `providers` to configure the {@link Injector} provisioned for this * Component Instance. @@ -137,8 +85,8 @@ export abstract class DynamicComponentLoader { * template: 'Parent' * }) * class MyApp { - * constructor(dcl: DynamicComponentLoader, elementRef: ElementRef) { - * dcl.loadNextToLocation(ChildComponent, elementRef); + * constructor(dcl: DynamicComponentLoader, viewContainerRef: ViewContainerRef) { + * dcl.loadNextToLocation(ChildComponent, viewContainerRef); * } * } * @@ -152,15 +100,14 @@ export abstract class DynamicComponentLoader { * Child * ``` */ - abstract loadNextToLocation(type: Type, location: ElementRef, providers?: ResolvedProvider[], + abstract loadNextToLocation(type: Type, location: ViewContainerRef, + providers?: ResolvedProvider[], projectableNodes?: any[][]): Promise; } @Injectable() export class DynamicComponentLoader_ extends DynamicComponentLoader { - constructor(private _compiler: ComponentResolver, private _viewManager: AppViewManager) { - super(); - } + constructor(private _compiler: ComponentResolver) { super(); } loadAsRoot(type: Type, overrideSelectorOrNode: string | any, injector: Injector, onDispose?: () => void, projectableNodes?: any[][]): Promise { @@ -175,20 +122,11 @@ export class DynamicComponentLoader_ extends DynamicComponentLoader { }); } - loadIntoLocation(type: Type, hostLocation: ElementRef, anchorName: string, - providers: ResolvedProvider[] = null, - projectableNodes: any[][] = null): Promise { - return this.loadNextToLocation( - type, this._viewManager.getNamedElementInComponentView(hostLocation, anchorName), providers, - projectableNodes); - } - - loadNextToLocation(type: Type, location: ElementRef, providers: ResolvedProvider[] = null, + loadNextToLocation(type: Type, location: ViewContainerRef, providers: ResolvedProvider[] = null, projectableNodes: any[][] = null): Promise { return this._compiler.resolveComponent(type).then(componentFactory => { - var viewContainer = this._viewManager.getViewContainer(location); - return viewContainer.createComponent(componentFactory, viewContainer.length, providers, - projectableNodes); + return location.createComponent(componentFactory, location.length, providers, + projectableNodes); }); } } diff --git a/modules/angular2/src/core/linker/element.ts b/modules/angular2/src/core/linker/element.ts index acc3ccadb9..d940ac97a6 100644 --- a/modules/angular2/src/core/linker/element.ts +++ b/modules/angular2/src/core/linker/element.ts @@ -6,37 +6,30 @@ import {Injector} from 'angular2/src/core/di'; import {AppView} from './view'; import {ViewType} from './view_type'; -import {ElementRef_} from './element_ref'; +import {ElementRef} from './element_ref'; import {ViewContainerRef, ViewContainerRef_} from './view_container_ref'; import {QueryList} from './query_list'; +/** + * An AppElement is created for elements that have a ViewContainerRef, + * a nested component or a