Skip to content

Commit b51d8dd

Browse files
crisbetomhevery
authored andcommitted
fix(ivy): error for empty bindings on ng-template (angular#30829)
Fixes Ivy throwing an error if it runs into an empty property binding on an `ng-template` (e.g. `<ng-template [something]=""></ng-template>`) by not generating an update instruction for it. Fixes angular#30801. This PR resoves FW-1356. PR Close angular#30829
1 parent ea2d453 commit b51d8dd

File tree

3 files changed

+43
-4
lines changed

3 files changed

+43
-4
lines changed

packages/common/test/directives/ng_template_outlet_spec.ts

+14
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,20 @@ describe('NgTemplateOutlet', () => {
204204
fixture.componentInstance.value = 'baz';
205205
detectChangesAndExpectText('');
206206
});
207+
208+
// https://github.com/angular/angular/issues/30801
209+
it('should not throw if the context is left blank', () => {
210+
const template = `
211+
<ng-template #testTemplate>test</ng-template>
212+
<ng-template [ngTemplateOutlet]="testTemplate" [ngTemplateOutletContext]=""></ng-template>
213+
`;
214+
215+
expect(() => {
216+
fixture = createTestComponent(template);
217+
detectChangesAndExpectText('test');
218+
}).not.toThrow();
219+
});
220+
207221
});
208222

209223
@Injectable()

packages/compiler-cli/test/compliance/r3_compiler_compliance_spec.ts

+22
Original file line numberDiff line numberDiff line change
@@ -2932,6 +2932,28 @@ describe('compiler compliance', () => {
29322932
expectEmit(source, SomeDirectiveDefinition, 'Incorrect SomeDirective.ngDirectiveDef');
29332933
});
29342934

2935+
it('should not throw for empty property bindings on ng-template', () => {
2936+
const files = {
2937+
app: {
2938+
'example.ts': `
2939+
import {Component, NgModule} from '@angular/core';
2940+
2941+
@Component({
2942+
selector: 'my-app',
2943+
template: '<ng-template [id]=""></ng-template>'
2944+
})
2945+
export class MyComponent {
2946+
}
2947+
2948+
@NgModule({declarations: [MyComponent]})
2949+
export class MyModule {}`
2950+
}
2951+
};
2952+
2953+
expect(() => compile(files, angularFiles)).not.toThrow();
2954+
});
2955+
2956+
29352957
});
29362958

29372959
describe('inherited base classes', () => {

packages/compiler/src/render3/view/template.ts

+7-4
Original file line numberDiff line numberDiff line change
@@ -1024,10 +1024,13 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
10241024
attrs.forEach(input => {
10251025
if (input instanceof t.BoundAttribute) {
10261026
const value = input.value.visit(this._valueConverter);
1027-
this.allocateBindingSlots(value);
1028-
this.updateInstruction(
1029-
templateIndex, template.sourceSpan, R3.property,
1030-
() => [o.literal(input.name), this.convertPropertyBinding(context, value, true)]);
1027+
1028+
if (value !== undefined) {
1029+
this.allocateBindingSlots(value);
1030+
this.updateInstruction(
1031+
templateIndex, template.sourceSpan, R3.property,
1032+
() => [o.literal(input.name), this.convertPropertyBinding(context, value, true)]);
1033+
}
10311034
}
10321035
});
10331036
}

0 commit comments

Comments
 (0)