diff --git a/packages/language-service/src/diagnostics.ts b/packages/language-service/src/diagnostics.ts index 755a7e1df9..2ee1e31841 100644 --- a/packages/language-service/src/diagnostics.ts +++ b/packages/language-service/src/diagnostics.ts @@ -71,9 +71,12 @@ export function getDeclarationDiagnostics( report( `Component '${declaration.type.name}' is not included in a module and will not be available inside a template. Consider adding it to a NgModule declaration`); } - if (!declaration.metadata.template !.template && - !declaration.metadata.template !.templateUrl) { - report(`Component ${declaration.type.name} must have a template or templateUrl`); + const {template, templateUrl} = declaration.metadata.template !; + if (template === null && !templateUrl) { + report(`Component '${declaration.type.name}' must have a template or templateUrl`); + } else if (template && templateUrl) { + report( + `Component '${declaration.type.name}' must not have both template and templateUrl`); } } else { if (!directives) { diff --git a/packages/language-service/test/diagnostics_spec.ts b/packages/language-service/test/diagnostics_spec.ts index eab1c1e6ac..07a77c2872 100644 --- a/packages/language-service/test/diagnostics_spec.ts +++ b/packages/language-service/test/diagnostics_spec.ts @@ -175,6 +175,22 @@ describe('diagnostics', () => { }); }); + // Issue #19406 + it('should allow empty template', () => { + const appComponent = ` + import { Component } from '@angular/core'; + + @Component({ + template : '', + }) + export class AppComponent {} + `; + const fileName = '/app/app.component.ts'; + mockHost.override(fileName, appComponent); + const diagnostics = ngService.getDiagnostics(fileName); + expect(diagnostics).toEqual([]); + }); + // Issue #15460 it('should be able to find members defined on an ancestor type', () => { const app_component = `