Josh Cunningham
Josh Cunningham

Reputation: 31

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:

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

}

Upvotes: 3

Views: 3427

Answers (2)

srWorks
srWorks

Reputation: 51

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

Upvotes: 5

Alan Grosz
Alan Grosz

Reputation: 1325

I found a stackblitz that maybe can help you https://stackblitz.com/edit/angular-open-window.

Obviously it can. I just learned something new :P

Upvotes: 0

Related Questions