From 46502e4d6111e8b92bd2fc0a6411fc83b32a9ecc Mon Sep 17 00:00:00 2001 From: Tobias Bosch Date: Thu, 23 Jul 2015 14:27:49 -0700 Subject: [PATCH] fix(projection): allow more bound render elements than app elements. Fixes #3236 Closes #3247 --- modules/angular2/src/core/compiler/view.ts | 6 +++--- modules/angular2/src/render/api.ts | 4 ++++ .../src/render/dom/view/proto_view_merger.ts | 7 ++++--- .../test/core/compiler/compiler_spec.ts | 2 +- .../compiler/projection_integration_spec.ts | 20 +++++++++++++++++++ .../core/compiler/view_manager_utils_spec.ts | 7 ++++--- 6 files changed, 36 insertions(+), 10 deletions(-) diff --git a/modules/angular2/src/core/compiler/view.ts b/modules/angular2/src/core/compiler/view.ts index 9237d2de44..216514374a 100644 --- a/modules/angular2/src/core/compiler/view.ts +++ b/modules/angular2/src/core/compiler/view.ts @@ -37,8 +37,8 @@ export class AppProtoViewMergeMapping { this.renderProtoViewRef = renderProtoViewMergeMapping.mergedProtoViewRef; this.renderFragmentCount = renderProtoViewMergeMapping.fragmentCount; this.renderElementIndices = renderProtoViewMergeMapping.mappedElementIndices; - this.renderInverseElementIndices = - inverseIndexMapping(this.renderElementIndices, this.renderElementIndices.length); + this.renderInverseElementIndices = inverseIndexMapping( + this.renderElementIndices, renderProtoViewMergeMapping.mappedElementCount); this.renderTextIndices = renderProtoViewMergeMapping.mappedTextIndices; this.hostElementIndicesByViewIndex = renderProtoViewMergeMapping.hostElementIndicesByViewIndex; this.nestedViewIndicesByElementIndex = @@ -48,7 +48,7 @@ export class AppProtoViewMergeMapping { } function inverseIndexMapping(input: number[], resultLength: number): number[] { - var result = ListWrapper.createFixedSize(resultLength); + var result = ListWrapper.createGrowableSize(resultLength); for (var i = 0; i < input.length; i++) { var value = input[i]; if (isPresent(value)) { diff --git a/modules/angular2/src/render/api.ts b/modules/angular2/src/render/api.ts index fd12c6732a..08ef3c858f 100644 --- a/modules/angular2/src/render/api.ts +++ b/modules/angular2/src/render/api.ts @@ -307,6 +307,10 @@ export class RenderProtoViewMergeMapping { // Mappings of nested ProtoViews are in depth first order, with all // indices for one ProtoView in a consecuitve block. public mappedElementIndices: number[], + // Number of bound render element. + // Note: This could be more than the original ones + // as we might have bound a new element for projecting bound text nodes. + public mappedElementCount: number, // Mapping from app text index to render text index. // Mappings of nested ProtoViews are in depth first order, with all // indices for one ProtoView in a consecuitve block. diff --git a/modules/angular2/src/render/dom/view/proto_view_merger.ts b/modules/angular2/src/render/dom/view/proto_view_merger.ts index ce4ff6e829..8224950344 100644 --- a/modules/angular2/src/render/dom/view/proto_view_merger.ts +++ b/modules/angular2/src/render/dom/view/proto_view_merger.ts @@ -56,9 +56,10 @@ export function mergeProtoViewsRecursively(protoViewRefs: List>, diff --git a/modules/angular2/test/core/compiler/compiler_spec.ts b/modules/angular2/test/core/compiler/compiler_spec.ts index e4e3bb3a17..4f10d31e13 100644 --- a/modules/angular2/test/core/compiler/compiler_spec.ts +++ b/modules/angular2/test/core/compiler/compiler_spec.ts @@ -74,7 +74,7 @@ export function main() { renderCompiler.spy('mergeProtoViewsRecursively') .andCallFake((protoViewRefs: List>) => { return PromiseWrapper.resolve(new renderApi.RenderProtoViewMergeMapping( - new MergedRenderProtoViewRef(protoViewRefs), 1, [], [], [], [null])); + new MergedRenderProtoViewRef(protoViewRefs), 1, [], 0, [], [], [null])); }); // TODO spy on .compile and return RenderProtoViewRef, same for compileHost rootProtoView = createRootProtoView(directiveResolver, MainComponent); diff --git a/modules/angular2/test/core/compiler/projection_integration_spec.ts b/modules/angular2/test/core/compiler/projection_integration_spec.ts index 89241887b8..aeafe43460 100644 --- a/modules/angular2/test/core/compiler/projection_integration_spec.ts +++ b/modules/angular2/test/core/compiler/projection_integration_spec.ts @@ -92,6 +92,26 @@ export function main() { }); })); + + it('should support projecting text interpolation to a non bound element with other bound elements after it', + inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => { + tcb.overrideView(Simple, new viewAnn.View({ + template: 'SIMPLE(
EL
)', + directives: [] + })) + .overrideView( + MainComp, + new viewAnn.View({template: '{{text}}', directives: [Simple]})) + .createAsync(MainComp) + .then((main) => { + + main.componentInstance.text = 'A'; + main.detectChanges(); + expect(main.nativeElement).toHaveText('SIMPLE(AEL)'); + async.done(); + }); + })); + it('should not show the light dom even if there is no content tag', inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => { tcb.overrideView(MainComp, diff --git a/modules/angular2/test/core/compiler/view_manager_utils_spec.ts b/modules/angular2/test/core/compiler/view_manager_utils_spec.ts index b29606c46f..57bfc53a7a 100644 --- a/modules/angular2/test/core/compiler/view_manager_utils_spec.ts +++ b/modules/angular2/test/core/compiler/view_manager_utils_spec.ts @@ -324,9 +324,10 @@ function _createProtoView(type: ViewType, binders: ElementBinder[] = null) { } var hostElementIndicesByViewIndex = calcHostElementIndicesByViewIndex(res); if (type === ViewType.EMBEDDED || type === ViewType.HOST) { - res.mergeMapping = new AppProtoViewMergeMapping(new RenderProtoViewMergeMapping( - null, hostElementIndicesByViewIndex.length, mappedElementIndices, [], - hostElementIndicesByViewIndex, countNestedProtoViews(res))); + res.mergeMapping = new AppProtoViewMergeMapping( + new RenderProtoViewMergeMapping(null, hostElementIndicesByViewIndex.length, + mappedElementIndices, mappedElementIndices.length, [], + hostElementIndicesByViewIndex, countNestedProtoViews(res))); } return res; }