diff --git a/modules/angular2/src/compiler/html_tags.ts b/modules/angular2/src/compiler/html_tags.ts index 5fb4db1b4e..1253b94ae2 100644 --- a/modules/angular2/src/compiler/html_tags.ts +++ b/modules/angular2/src/compiler/html_tags.ts @@ -311,7 +311,6 @@ export class HtmlTagDefinition { // This implementation does not fully conform to the HTML5 spec. var TAG_DEFINITIONS: {[key: string]: HtmlTagDefinition} = { 'link': new HtmlTagDefinition({isVoid: true}), - 'ng-content': new HtmlTagDefinition({isVoid: true}), 'img': new HtmlTagDefinition({isVoid: true}), 'input': new HtmlTagDefinition({isVoid: true}), 'hr': new HtmlTagDefinition({isVoid: true}), diff --git a/modules/angular2/src/compiler/template_parser.ts b/modules/angular2/src/compiler/template_parser.ts index 80dd89d1a2..9e4fcd62b0 100644 --- a/modules/angular2/src/compiler/template_parser.ts +++ b/modules/angular2/src/compiler/template_parser.ts @@ -228,6 +228,11 @@ class TemplateParseVisitor implements HtmlAstVisitor { hasInlineTemplates ? null : component.findNgContentIndex(elementCssSelector); var parsedElement; if (preparsedElement.type === PreparsedElementType.NG_CONTENT) { + if (isPresent(element.children) && element.children.length > 0) { + this._reportError( + ` element cannot have content. must be immediately followed by `, + element.sourceSpan); + } parsedElement = new NgContentAst(this.ngContentCount++, elementNgContentIndex, element.sourceSpan); } else if (isTemplateElement) { diff --git a/modules/angular2/test/compiler/html_parser_spec.ts b/modules/angular2/test/compiler/html_parser_spec.ts index 91400e20ac..f851c1ec1c 100644 --- a/modules/angular2/test/compiler/html_parser_spec.ts +++ b/modules/angular2/test/compiler/html_parser_spec.ts @@ -86,8 +86,8 @@ export function main() { }); it('should tolerate end tags for void elements when they have no content', () => { - expect(humanizeDom(parser.parse('', 'TestComp'))) - .toEqual([[HtmlElementAst, 'ng-content', 0]]); + expect(humanizeDom(parser.parse('', 'TestComp'))) + .toEqual([[HtmlElementAst, 'input', 0]]); }); it('should support optional end tags', () => { @@ -215,27 +215,27 @@ export function main() { }); it('should report text content in void elements', () => { - let errors = parser.parse('content', 'TestComp').errors; + let errors = parser.parse('content', 'TestComp').errors; expect(errors.length).toEqual(1); expect(humanizeErrors(errors)) .toEqual([ [ - 'ng-content', - 'Void elements do not have end tags (they can not have content) "ng-content"', - '0:19' + 'input', + 'Void elements do not have end tags (they can not have content) "input"', + '0:14' ] ]); }); it('should report html content in void elements', () => { - let errors = parser.parse('

', 'TestComp').errors; + let errors = parser.parse('

', 'TestComp').errors; expect(errors.length).toEqual(1); expect(humanizeErrors(errors)) .toEqual([ [ - 'ng-content', - 'Void elements do not have end tags (they can not have content) "ng-content"', - '0:19' + 'input', + 'Void elements do not have end tags (they can not have content) "input"', + '0:14' ] ]); }); diff --git a/modules/angular2/test/compiler/template_parser_spec.ts b/modules/angular2/test/compiler/template_parser_spec.ts index 36fc5d6e72..574c054e10 100644 --- a/modules/angular2/test/compiler/template_parser_spec.ts +++ b/modules/angular2/test/compiler/template_parser_spec.ts @@ -689,6 +689,12 @@ There is no directive with "exportAs" set to "dirA" ("
]#a="dirA">< }); describe('error cases', () => { + it('should report when ng-content has content', () => { + expect(() => parse('content', [])) + .toThrowError(`Template parse errors: + element cannot have content. must be immediately followed by ("[ERROR ->]content"): TestComp@0:0`); + }); + it('should report invalid property names', () => { expect(() => parse('
', [])).toThrowError(`Template parse errors: Can't bind to 'invalidProp' since it isn't a known native property ("
][invalid-prop]>
"): TestComp@0:5`);