diff --git a/modules/@angular/compiler/src/template_parser/template_parser.ts b/modules/@angular/compiler/src/template_parser/template_parser.ts index 207184a8ac..9fd3a4cea8 100644 --- a/modules/@angular/compiler/src/template_parser/template_parser.ts +++ b/modules/@angular/compiler/src/template_parser/template_parser.ts @@ -815,10 +815,11 @@ class TemplateParseVisitor implements html.Visitor { bindingType = PropertyBindingType.Property; if (!this._schemaRegistry.hasProperty(elementName, boundPropertyName, this._schemas)) { let errorMsg = - `Can't bind to '${boundPropertyName}' since it isn't a known native property`; + `Can't bind to '${boundPropertyName}' since it isn't a known property of '${elementName}'.`; if (elementName.indexOf('-') !== -1) { errorMsg += - `. To ignore this error on custom elements, add the "CUSTOM_ELEMENTS_SCHEMA" to the NgModule of this component`; + `\n1. If '${elementName}' is an Angular component and it has '${boundPropertyName}' input, then verify that it is part of this module.` + + `\n2. If '${elementName}' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schema' of this component to suppress this message.\n`; } this._reportError(errorMsg, sourceSpan); } diff --git a/modules/@angular/compiler/test/template_parser/template_parser_spec.ts b/modules/@angular/compiler/test/template_parser/template_parser_spec.ts index 733c804cfc..ebb362bf92 100644 --- a/modules/@angular/compiler/test/template_parser/template_parser_spec.ts +++ b/modules/@angular/compiler/test/template_parser/template_parser_spec.ts @@ -252,6 +252,17 @@ export function main() { `Template parse errors:\nInvalid property name 'bar.foo' ("

][bar.foo]>"): TestComp@0:3`); }); + describe('errors', () => { + it('should throw error when binding to an unkonown property', () => { + expect(() => parse('', [])) + .toThrowError(`Template parse errors: +Can't bind to 'invalidProp' since it isn't a known property of 'my-component'. +1. If 'my-component' is an Angular component and it has 'invalidProp' input, then verify that it is part of this module. +2. If 'my-component' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schema' of this component to suppress this message. + ("][invalidProp]="bar">"): TestComp@0:14`); + }); + }); + it('should parse bound properties via [...] and not report them as attributes', () => { expect(humanizeTplAst(parse('

', []))).toEqual([ [ElementAst, 'div'], @@ -1240,7 +1251,7 @@ Can't have multiple template bindings on one element. Use only one attribute nam 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 ("
][invalidProp]>
"): TestComp@0:5`); +Can't bind to 'invalidProp' since it isn't a known property of 'div'. ("
][invalidProp]>
"): TestComp@0:5`); }); it('should report invalid host property names', () => { @@ -1250,7 +1261,7 @@ Can't bind to 'invalidProp' since it isn't a known native property ("
parse('
', [dirA])).toThrowError(`Template parse errors: -Can't bind to 'invalidProp' since it isn't a known native property ("[ERROR ->]
"): TestComp@0:0, Directive DirA`); +Can't bind to 'invalidProp' since it isn't a known property of 'div'. ("[ERROR ->]
"): TestComp@0:0, Directive DirA`); }); it('should report errors in expressions', () => { diff --git a/modules/@angular/core/test/linker/integration_spec.ts b/modules/@angular/core/test/linker/integration_spec.ts index bb437d20fa..2a2a2d76c3 100644 --- a/modules/@angular/core/test/linker/integration_spec.ts +++ b/modules/@angular/core/test/linker/integration_spec.ts @@ -1743,7 +1743,7 @@ function declareTests({useJit}: {useJit: boolean}) { PromiseWrapper.catchError(tcb.createAsync(MyComp), (e) => { expect(e.message).toEqual( - `Template parse errors:\nCan't bind to 'unknown' since it isn't a known native property ("
]unknown="{{ctxProp}}">
"): MyComp@0:5`); + `Template parse errors:\nCan't bind to 'unknown' since it isn't a known property of 'div'. ("
]unknown="{{ctxProp}}">
"): MyComp@0:5`); async.done(); return null; });