Skip to content
Permalink
Browse files

fix(ivy): ngTemplateOutlet error when switching between null and temp…

…late value (#32160)

Fixes an error that is thrown by `ngTemplateOutlet` under Ivy when switching from a template to null and back to a template. The error is thrown because the reference to the previous ViewRef is never cleared and the directive tries to detach a view that has already been detached.

Fixes #32060.

PR Close #32160
  • Loading branch information...
crisbeto authored and AndrewKushnir committed Aug 16, 2019
1 parent 994264c commit c2868de25a0fe4e14e4da4aae6aa2d5867711d05
@@ -55,18 +55,17 @@ export class NgTemplateOutlet implements OnChanges {
const recreateView = this._shouldRecreateView(changes);

if (recreateView) {
const viewContainerRef = this._viewContainerRef;

if (this._viewRef) {
this._viewContainerRef.remove(this._viewContainerRef.indexOf(this._viewRef));
viewContainerRef.remove(viewContainerRef.indexOf(this._viewRef));
}

if (this.ngTemplateOutlet) {
this._viewRef = this._viewContainerRef.createEmbeddedView(
this.ngTemplateOutlet, this.ngTemplateOutletContext);
}
} else {
if (this._viewRef && this.ngTemplateOutletContext) {
this._updateExistingContext(this.ngTemplateOutletContext);
}
this._viewRef = this.ngTemplateOutlet ?
viewContainerRef.createEmbeddedView(this.ngTemplateOutlet, this.ngTemplateOutletContext) :
null;
} else if (this._viewRef && this.ngTemplateOutletContext) {
this._updateExistingContext(this.ngTemplateOutletContext);
}
}

@@ -96,9 +95,8 @@ export class NgTemplateOutlet implements OnChanges {
}
}
return false;
} else {
return true;
}
return true;
}

private _updateExistingContext(ctx: Object): void {
@@ -218,6 +218,25 @@ describe('NgTemplateOutlet', () => {
}).not.toThrow();
});

it('should not throw when switching from template to null and back to template', async(() => {
const template = `<tpl-refs #refs="tplRefs"><ng-template>foo</ng-template></tpl-refs>` +
`<ng-container [ngTemplateOutlet]="currentTplRef"></ng-container>`;
fixture = createTestComponent(template);
fixture.detectChanges();
const refs = fixture.debugElement.children[0].references !['refs'];

setTplRef(refs.tplRefs.first);
detectChangesAndExpectText('foo');

setTplRef(null);
detectChangesAndExpectText('');

expect(() => {
setTplRef(refs.tplRefs.first);
detectChangesAndExpectText('foo');
}).not.toThrow();
}));

});

@Injectable()

0 comments on commit c2868de

Please sign in to comment.
You can’t perform that action at this time.