diff --git a/packages/common/test/directives/ng_template_outlet_spec.ts b/packages/common/test/directives/ng_template_outlet_spec.ts index 9226e5acbe..4f349b1776 100644 --- a/packages/common/test/directives/ng_template_outlet_spec.ts +++ b/packages/common/test/directives/ng_template_outlet_spec.ts @@ -204,6 +204,20 @@ describe('NgTemplateOutlet', () => { fixture.componentInstance.value = 'baz'; detectChangesAndExpectText(''); }); + + // https://github.com/angular/angular/issues/30801 + it('should not throw if the context is left blank', () => { + const template = ` + test + + `; + + expect(() => { + fixture = createTestComponent(template); + detectChangesAndExpectText('test'); + }).not.toThrow(); + }); + }); @Injectable() diff --git a/packages/compiler-cli/test/compliance/r3_compiler_compliance_spec.ts b/packages/compiler-cli/test/compliance/r3_compiler_compliance_spec.ts index 82b4379423..78b52bc5a4 100644 --- a/packages/compiler-cli/test/compliance/r3_compiler_compliance_spec.ts +++ b/packages/compiler-cli/test/compliance/r3_compiler_compliance_spec.ts @@ -2932,6 +2932,28 @@ describe('compiler compliance', () => { expectEmit(source, SomeDirectiveDefinition, 'Incorrect SomeDirective.ngDirectiveDef'); }); + it('should not throw for empty property bindings on ng-template', () => { + const files = { + app: { + 'example.ts': ` + import {Component, NgModule} from '@angular/core'; + + @Component({ + selector: 'my-app', + template: '' + }) + export class MyComponent { + } + + @NgModule({declarations: [MyComponent]}) + export class MyModule {}` + } + }; + + expect(() => compile(files, angularFiles)).not.toThrow(); + }); + + }); describe('inherited base classes', () => { diff --git a/packages/compiler/src/render3/view/template.ts b/packages/compiler/src/render3/view/template.ts index d7316a84af..2a742933b4 100644 --- a/packages/compiler/src/render3/view/template.ts +++ b/packages/compiler/src/render3/view/template.ts @@ -1024,10 +1024,13 @@ export class TemplateDefinitionBuilder implements t.Visitor, LocalResolver attrs.forEach(input => { if (input instanceof t.BoundAttribute) { const value = input.value.visit(this._valueConverter); - this.allocateBindingSlots(value); - this.updateInstruction( - templateIndex, template.sourceSpan, R3.property, - () => [o.literal(input.name), this.convertPropertyBinding(context, value, true)]); + + if (value !== undefined) { + this.allocateBindingSlots(value); + this.updateInstruction( + templateIndex, template.sourceSpan, R3.property, + () => [o.literal(input.name), this.convertPropertyBinding(context, value, true)]); + } } }); }