简体   繁体   中英

issue with angular 8 cdk portal new window

enter code herei'm trying to open my component in new window like this example:

https://stackblitz.com/edit/angular-open-window

the window opens but without my component in it and the console gives my this error: VideoConferenceRequestsComponent.html:116 ERROR Error: Must provide a portal to attach

and this is my code but it is in angular 8, not 7 as the example above

window component ts

 ```import {Component, ViewChild, OnInit, ComponentFactoryResolver, ApplicationRef, Injector, OnDestroy, Output, EventEmitter } from '@angular/core';
import {CdkPortal,DomPortalHost} from '@angular/cdk/portal';

@Component({
  selector: 'window',
  templateUrl: './window.component.html',
  styleUrls: ['./window.component.scss']
})
export class WindowComponent implements OnInit, OnDestroy {
  @Output() close : EventEmitter<any> = new EventEmitter();

// STEP 1: get a reference to the portal
@ViewChild('CdkPortal', {static: true}) 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()
  debugger
  this.close.emit();
}
}```

window component html

```<ng-container *cdkPortal>
    <ng-content></ng-content>
  </ng-container>```

parent component ts:

it contains a flag just like the example above showPortal = false;

parent component HTML

```<button (click)="showPortal = true">open me!</button>

<window *ngIf="showPortal" (close)="showPortal = false">
  <h2>Hello world from amother window!!</h2>
  <button (click)="showPortal = false">Close me!</button>
</window>```

shared module where I imported portal module

```import { MaterialModule } from './../material-module';
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { ReactiveFormsModule, FormsModule } from '@angular/forms';
import { TranslateModule } from '@ngx-translate/core';
import { SharedHeaderComponent } from './components/shared-header/shared-header.component';
import { RouterModule } from '@angular/router';
import { NgSelectModule } from '@ng-select/ng-select';    
import { SharedFooterComponent } from './components/shared-footer/shared-footer.component';
import { SharedNavbarComponent } from './components/shared-navbar/shared-navbar.component';
import { HosptailDetailsComponent } from './components/hosptail-details/hosptail-details.component';
import { ApiInterceptor } from './interceptors/api-interceptor';
import { JwtInterceptor } from './interceptors/jwt.interceptor';
import { ErrorInterceptor } from './interceptors/error.interceptor';
import { NgxIntlTelInputModule } from 'ngx-intl-tel-input';
import { SharedSidebarComponent } from './components/shared-sidebar/shared-sidebar.component';
import { LiveVideoPopupComponent } from './components/_popup/live-video-popup/live-video-popup.component';
import { ModalBasicComponent } from './components/modal-basic/modal-basic.component';
import { SubscriberComponent } from './components/subscriber/subscriber.component';
import { PublisherComponent } from './components/publisher/publisher.component';
import { OpentokService } from './services/opentok.service';
import { PortalModule } from '@angular/cdk/portal';


@NgModule({
  declarations: [
    PublisherComponent,
    SubscriberComponent,
    SharedHeaderComponent,
    SharedFooterComponent,
    SharedNavbarComponent,
    HosptailDetailsComponent,
    SharedSidebarComponent,
    LiveVideoPopupComponent,
    ModalBasicComponent
  ],
  imports: [
    PortalModule,
    ReactiveFormsModule,
    TranslateModule,
    HttpClientModule,
    RouterModule,
    FormsModule,
    CommonModule,
    NgSelectModule,
    // SelectModule
    MaterialModule
  ],
  exports: [
    PortalModule,
    ReactiveFormsModule,
    FormsModule,
    TranslateModule,
    SharedHeaderComponent,
    SharedNavbarComponent,
    SharedFooterComponent,
    PublisherComponent,
    SubscriberComponent,
    LiveVideoPopupComponent,
    ModalBasicComponent,
    HttpClientModule,
    NgSelectModule,
    NgxIntlTelInputModule
  ],
  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: ApiInterceptor, multi: true },
    { provide: HTTP_INTERCEPTORS, useClass: JwtInterceptor, multi: true },
    { provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true },
    OpentokService
  ]
})
export class SharedModule { }```

you can solve this issue with two options

1-Move your code to ngAfterViewInit() to gave time to load your component

ngAfterViewInit() {
// 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);

}

2-Or setTimeOut for code inside ngOnInit()

ngOnInit() {
setTimeout(() => {
  // 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);
}, 1000);

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM