首页 > 解决方案 > angular 8 cdk 门户新窗口的问题

问题描述

在这里输入代码我试图在新窗口中打开我的组件,如下例所示:

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

窗口打开,但其中没有我的组件,控制台给出了这个错误:VideoConferenceRequestsComponent.html:116 错误错误:必须提供一个门户来附加

这是我的代码,但它是角度 8,而不是上面示例中的 7

窗口组件 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();
}
}```

窗口组件html

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

父组件 ts:

它包含一个标志,就像上面的例子一样 showPortal = false;

父组件 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>```

我导入门户模块的共享模块

```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 { }```

标签: javascriptangulartypescriptnpmangular8

解决方案


你可以用两个选项来解决这个问题

1-将您的代码移动到 ngAfterViewInit() 以便有时间加载您的组件

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-或 setTimeOut 用于 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);

}


推荐阅读