Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 9 CDK Portal Error: Must provide a portal to attach

I am having a difficult time with something that seems pretty straightforward. I am trying to open a new window with some html in angular 9. Everytime it runs, I see a window popup for a second, before it fails and throws the following error:

Error: Must provide a portal to attach
    at throwNullPortalError (portal.js:23)
    at DomPortalHost.attach (portal.js:320)
    at GraphPopoutComponent.ngOnInit (graph-popout.component.ts:43)
    at callHook (core.js:4686)
    at callHooks (core.js:4650)
    at executeInitAndCheckHooks (core.js:4591)
    at refreshView (core.js:11814)
    at refreshDynamicEmbeddedViews (core.js:13154)
    at refreshView (core.js:11819)
    at refreshComponent (core.js:13229)

Before anyone asks:

  • yes, I have included PortalModule in my app.module.ts
  • angular 9.0.7
  • angular/cdk, angular/material 9.1.3
  • i do have nested modules, would that cause an issue with the PortalModule?

Here is my code for reference:

graph.component.html

.
.
.
<app-graph-popout *ngIf="openPortal">
  <h1>IT WORKS</h1>
</app-graph-popout>

graph.component.ts

.
.
.
togglePortal() {
    this.openPortal = true;
  }

graph-popout.component.ts

@Component({
  selector: 'app-graph-popout',
  // templateUrl: './graph-popout.component.html',
  template: `
    <ng-container *cdkPortal>
      <ng-content></ng-content>
    </ng-container>
  `


})
export class GraphPopoutComponent implements OnInit, OnDestroy {

  // STEP 1: get a reference to the portal
  @ViewChild(CdkPortal) portal: CdkPortal;

  // STEP 2: save a reference to the window so we can close it
  private externalWindow = null;

  // STEP 3: Inject all the required dependencies for a PortalHost
  constructor(
    private componentFactoryResolver: ComponentFactoryResolver,
    private applicationRef: ApplicationRef,
    private injector: Injector) { }

  ngOnInit() {
    // STEP 4: create an external window
    this.externalWindow = window.open('', '', 'width=600,height=400,left=200,top=200');

    // STEP 5: create a PortalHost with the body of the new window document
    const host = new DomPortalHost(
      this.externalWindow.document.body,
      this.componentFactoryResolver,
      this.applicationRef,
      this.injector
    );

    // STEP 6: Attach the portal
    host.attach(this.portal);
  }

  ngOnDestroy() {
    // STEP 7: close the window when this component destroyed
    this.externalWindow.close();
  }

}
like image 863
Josh Cunningham Avatar asked Dec 08 '25 16:12

Josh Cunningham


1 Answers

Faced the same problem. Following the example @angular doc moved the code block from ngOnInit to ngAfterViewInit which solved this problem.

Modified working sample @stackblitz uses angular 10.0.3

like image 133
srWorks Avatar answered Dec 11 '25 13:12

srWorks



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!