1

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);
}

Demo in Stackblitz

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?

kremerd
  • 1,496
  • 15
  • 24
  • 1
    You can access the `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 to `body`: `this.viewContainerRef.detach()`, [like this](https://stackblitz.com/edit/angular-component-body-fg5fuj). – skink Sep 15 '22 at 17:09
  • Wow, this is cool! Related question: Is it possible to get a `viewContainerRef` in a service to extract this logic? – kremerd Sep 19 '22 at 08:58
  • Unfortunately, nope: https://stackoverflow.com/questions/40636840/how-can-i-inject-viewcontainerref-into-a-service – skink Sep 20 '22 at 11:40
  • 1
    Although, apparently there's something new in Angular 14.1 that could help you: https://netbasal.com/getting-to-know-the-createcomponent-api-in-angular-22fb115f08e2 – skink Sep 20 '22 at 11:48

0 Answers0