fix(render): recurse into components/embedded templates not until all elements in a view have been visited

Fixes #4551
Closes #4601
This commit is contained in:
Tobias Bosch
2015-10-07 17:15:12 -07:00
parent ff77230edb
commit 6d4bd5d901
11 changed files with 294 additions and 133 deletions

View File

@ -74,7 +74,7 @@ export class CommandCompiler {
interface CommandFactory<R> {
createText(value: string, isBound: boolean, ngContentIndex: number): R;
createNgContent(ngContentIndex: number): R;
createNgContent(index: number, ngContentIndex: number): R;
createBeginElement(name: string, attrNameAndValues: string[], eventTargetAndNames: string[],
variableNameAndValues: string[], directives: CompileDirectiveMetadata[],
isBound: boolean, ngContentIndex: number): R;
@ -114,7 +114,9 @@ class RuntimeCommandFactory implements CommandFactory<TemplateCmd> {
createText(value: string, isBound: boolean, ngContentIndex: number): TemplateCmd {
return text(value, isBound, ngContentIndex);
}
createNgContent(ngContentIndex: number): TemplateCmd { return ngContent(ngContentIndex); }
createNgContent(index: number, ngContentIndex: number): TemplateCmd {
return ngContent(index, ngContentIndex);
}
createBeginElement(name: string, attrNameAndValues: string[], eventTargetAndNames: string[],
variableNameAndValues: string[], directives: CompileDirectiveMetadata[],
isBound: boolean, ngContentIndex: number): TemplateCmd {
@ -169,8 +171,8 @@ class CodegenCommandFactory implements CommandFactory<string> {
createText(value: string, isBound: boolean, ngContentIndex: number): string {
return `${TEMPLATE_COMMANDS_MODULE_REF}text(${escapeSingleQuoteString(value)}, ${isBound}, ${ngContentIndex})`;
}
createNgContent(ngContentIndex: number): string {
return `${TEMPLATE_COMMANDS_MODULE_REF}ngContent(${ngContentIndex})`;
createNgContent(index: number, ngContentIndex: number): string {
return `${TEMPLATE_COMMANDS_MODULE_REF}ngContent(${index}, ${ngContentIndex})`;
}
createBeginElement(name: string, attrNameAndValues: string[], eventTargetAndNames: string[],
variableNameAndValues: string[], directives: CompileDirectiveMetadata[],
@ -221,7 +223,7 @@ class CommandBuilderVisitor<R> implements TemplateAstVisitor {
visitNgContent(ast: NgContentAst, context: any): any {
this.transitiveNgContentCount++;
this.result.push(this.commandFactory.createNgContent(ast.ngContentIndex));
this.result.push(this.commandFactory.createNgContent(ast.index, ast.ngContentIndex));
return null;
}
visitEmbeddedTemplate(ast: EmbeddedTemplateAst, context: any): any {

View File

@ -104,7 +104,7 @@ export class DirectiveAst implements TemplateAst {
}
export class NgContentAst implements TemplateAst {
constructor(public ngContentIndex: number, public sourceInfo: string) {}
constructor(public index: number, public ngContentIndex: number, public sourceInfo: string) {}
visit(visitor: TemplateAstVisitor, context: any): any {
return visitor.visitNgContent(this, context);
}

View File

@ -96,6 +96,8 @@ class TemplateParseVisitor implements HtmlAstVisitor {
selectorMatcher: SelectorMatcher;
errors: string[] = [];
directivesIndex = new Map<CompileDirectiveMetadata, number>();
ngContentCount: number = 0;
constructor(directives: CompileDirectiveMetadata[], private _exprParser: Parser,
private _schemaRegistry: ElementSchemaRegistry) {
this.selectorMatcher = new SelectorMatcher();
@ -207,7 +209,8 @@ class TemplateParseVisitor implements HtmlAstVisitor {
hasInlineTemplates ? null : component.findNgContentIndex(elementCssSelector);
var parsedElement;
if (preparsedElement.type === PreparsedElementType.NG_CONTENT) {
parsedElement = new NgContentAst(elementNgContentIndex, element.sourceInfo);
parsedElement =
new NgContentAst(this.ngContentCount++, elementNgContentIndex, element.sourceInfo);
} else if (isTemplateElement) {
this._assertNoComponentsNorElementBindingsOnTemplate(directives, elementProps, events,
element.sourceInfo);