Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 14 additions & 11 deletions modules/angular2/src/core/render/view_factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,13 +128,13 @@ class RenderViewBuilder<N> implements RenderCommandVisitor {
root = this.factory.createShadowRoot(el);
this.nativeShadowRoots.push(root);
}
this.parentStack.push(new Component(el, root, cmd, this.factory));
var component = new Component(el, root, cmd, this.factory, this.allBuilders);
this.parentStack.push(component);
return null;
}
visitEndComponent(context: any): any {
var c = <Component<N>>this.parent;
var template = this.factory.resolveComponentTemplate(c.cmd.templateId);
this._visitChildTemplate(template, c, c.shadowRoot);
c.build();
this._endElement();
return null;
}
Expand All @@ -143,7 +143,9 @@ class RenderViewBuilder<N> implements RenderCommandVisitor {
this._addChild(el, cmd.ngContentIndex);
this.boundElements.push(el);
if (cmd.isMerged) {
this._visitChildTemplate(cmd.children, this.parentComponent, null);
visitAll(
new RenderViewBuilder(this.parentComponent, null, null, this.allBuilders, this.factory),
cmd.children);
}
return null;
}
Expand Down Expand Up @@ -172,11 +174,6 @@ class RenderViewBuilder<N> implements RenderCommandVisitor {

private _endElement() { this.parentStack.pop(); }

private _visitChildTemplate(cmds: RenderTemplateCmd[], parent: Component<N>, rootNodesParent: N) {
visitAll(new RenderViewBuilder(parent, rootNodesParent, null, this.allBuilders, this.factory),
cmds);
}

private _addChild(node: N, ngContentIndex: number) {
var parent = this.parent;
if (isPresent(parent)) {
Expand All @@ -194,9 +191,12 @@ class RenderViewBuilder<N> implements RenderCommandVisitor {
class Component<N> {
private contentNodesByNgContentIndex: N[][] = [];
private projectingNgContentIndex: number = 0;
private viewBuilder: RenderViewBuilder<N>;

constructor(public hostElement: N, public shadowRoot: N, public cmd: RenderBeginComponentCmd,
public factory: NodeFactory<N>) {}
constructor(public hostElement: N, shadowRoot: N, public cmd: RenderBeginComponentCmd,
public factory: NodeFactory<N>, allBuilders: RenderViewBuilder<N>[]) {
this.viewBuilder = new RenderViewBuilder(this, shadowRoot, null, allBuilders, factory);
}
addContentNode(ngContentIndex: number, node: N) {
if (isBlank(ngContentIndex)) {
if (this.cmd.nativeShadow) {
Expand All @@ -215,6 +215,9 @@ class Component<N> {
this.contentNodesByNgContentIndex[ngContentIndex] :
[];
}
build() {
visitAll(this.viewBuilder, this.factory.resolveComponentTemplate(this.cmd.templateId));
}
}

function addAll(source: any[], target: any[]) {
Expand Down
26 changes: 26 additions & 0 deletions modules/angular2/test/core/linker/projection_integration_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,26 @@ export function main() {
});
}));

it('should project content components',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.overrideView(
Simple,
new ViewMetadata(
{template: 'SIMPLE({{0}}|<ng-content></ng-content>|{{2}})', directives: []}))
.overrideView(OtherComp, new ViewMetadata({template: '{{1}}', directives: []}))
.overrideView(MainComp, new ViewMetadata({
template: '<simple><other></other></simple>',
directives: [Simple, OtherComp]
}))
.createAsync(MainComp)
.then((main) => {

main.detectChanges();
expect(main.debugElement.nativeElement).toHaveText('SIMPLE(0|1|2)');
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,
Expand Down Expand Up @@ -453,6 +473,12 @@ class MainComp {
text: string = '';
}

@Component({selector: 'other'})
@View({template: '', directives: []})
class OtherComp {
text: string = '';
}

@Component({selector: 'simple', inputs: ['stringProp']})
@View({template: 'SIMPLE(<ng-content></ng-content>)', directives: []})
class Simple {
Expand Down
38 changes: 38 additions & 0 deletions modules/angular2/test/core/render/view_factory_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,28 @@ export function main() {
.toEqual(['1.1', '1.2', '1.3', '1.4', '2.1', '2.2', '3.1', '3.1']);
});

it('should store bound elements from the view before bound elements from content components',
() => {
componentTemplates.set(0, [
beginElement('a', ['id', '2.1'], [], true, null),
endElement(),
]);
componentTemplates.set(1, [
beginElement('a', ['id', '3.1'], [], true, null),
endElement(),
]);
var view = createRenderView(
[
beginComponent('a-comp', ['id', '1.1'], [], false, null, 0),
beginComponent('b-comp', ['id', '1.2'], [], false, null, 1),
endComponent(),
endComponent(),
],
null, nodeFactory);

expect(mapAttrs(view.boundElements, 'id')).toEqual(['1.1', '1.2', '2.1', '3.1']);
});

it('should store bound text nodes after the bound text nodes of the main template', () => {
componentTemplates.set(0, [
text('2.1', true, null),
Expand Down Expand Up @@ -374,6 +396,22 @@ export function main() {
});
});

it('should store bound text nodes from the view before bound text nodes from content components',
() => {
componentTemplates.set(0, [text('2.1', true, null)]);
componentTemplates.set(1, [text('3.1', true, null)]);
var view = createRenderView(
[
beginComponent('a-comp', [], [], false, null, 0),
beginComponent('b-comp', [], [], false, null, 1),
endComponent(),
endComponent(),
],
null, nodeFactory);

expect(mapText(view.boundTextNodes)).toEqual(['2.1', '3.1']);
});

describe('content projection', () => {
it('should remove non projected nodes', () => {
componentTemplates.set(0, []);
Expand Down