I would like to render an Angular component (an overlay) as a direct child of the documents body
element. Today this can be done as follows:
constructor(
private applicationRef: ApplicationRef,
private componentFactoryResolver: ComponentFactoryResolver,
@Inject(DOCUMENT) private document: Document,
private injector: Injector
) {}
public renderOverlayInBody(): void {
const overlayRef = this.componentFactoryResolver
.resolveComponentFactory(OverlayComponent)
.create(this.injector);
this.applicationRef.attachView(overlayRef.hostView);
const overlayRoot = (overlayRef.hostView as EmbeddedViewRef<unknown>)
.rootNodes[0] as HTMLElement;
// This component can be appended to any place in the DOM,
// in particular directly to the document body.
this.document.body.appendChild(overlayRoot);
}
Unfortunately, ComponentFactoryResolver
has been deprecated in Angular 13 and may be removed in Angular 16. The suggested replacement is ViewContainerRef.createComponent
:
constructor(private viewContainerRef: ViewContainerRef) {}
public ngOnInit(): void {
// This component can only be appended to the current one,
// in particular not directly to the document body.
this.viewContainerRef.createComponent(OverlayComponent);
}
While this is much simpler to read, it doesn't allow to render components as direct children of the documents body
element. Is there any way to do that, which doesn't rely on currently deprecated code?
overlayRoot
pretty much exactly like you're accessing it in the old code. The only difference is that you'll have to remove the rendered component before adding it tobody
:this.viewContainerRef.detach()
, like this. – SnookviewContainerRef
in a service to extract this logic? – Crawler