【发布时间】:2020-09-29 15:31:33
【问题描述】:
我对 Angular 比较陌生,并且有一个功能,我需要在单独的子窗口中弹出一个组件,在窗口关闭时我需要再次将其附加到父窗口
我已阅读有关角度门户的信息并决定使用它。我编写了以下服务来管理门户及其创建:
import { ApplicationRef, ComponentFactoryResolver, ComponentRef, Injectable, Injector, InjectionToken, Inject } from '@angular/core';
import { PopoutComponent } from '../popout/popout.component';
import { POPOUT_REFS } from './portal.token';
import { EventService } from './event.service';
@Injectable({
providedIn: 'root'
})
export class PortalService {
constructor(private injector: Injector,
private componentFactoryResolver: ComponentFactoryResolver,
private applicationRef: ApplicationRef,
private eventService: EventService ) {
this.eventService.popoutEvent$.subscribe((val) => {
if(val && this.isPopoutWindowOpen()) {
this.closePopoutWindow();
}
})
}
popOutComponent() {
const popoutWindow: Window = this.createWindow('POP_OUT_COMPONENT');
setTimeout(() => {
this.createPortal(popoutWindow);
}, 1000);
}
private createWindow(target): Window {
const ref = window.open("index.html", "_blank", "height=400; width=400;directories=0,titlebar=0,toolbar=0,location=0,status=0,menubar=no;", true);
setTimeout(() => {
ref.document.body.innerHTML = "";
}, 1000);
return ref;
}
private createPortal(popoutWindow: Window) {
if(popoutWindow) {
const outlet = new DomPortalOutlet(popoutWindow.document.body, this.componentFactoryResolver, this.applicationRef, this.injector);
const conatinerInstance = this.attachPopoutContainer(outlet);
this.attachUnloadEventToPopoutWindow(popoutWindow);
POPOUT_REFS['windowInstance'] = popoutWindow;
POPOUT_REFS['containerInstance'] = conatinerInstance;
POPOUT_REFS['portalOutlet'] = outlet;
}
}
private attachPopoutContainer(outlet: DomPortalOutlet) {
const containerPortal = new ComponentPortal(PopoutComponent, null, null);
const containerRef: ComponentRef<PopoutComponent> = outlet.attach(containerPortal);
return containerRef.instance;
}
private attachUnloadEventToPopoutWindow(popoutWindow: Window) {
popoutWindow.addEventListener("beforeunload", () => {
POPOUT_REFS['portalOutlet'].detach();
this.eventService.publishPopoutEvent(true);
});
}
isPopoutWindowOpen() {
return POPOUT_REFS['windowInstance'] && !POPOUT_REFS['windowInstance'].closed;
}
closePopoutWindow() {
Object.keys(POPOUT_REFS).forEach(popout => {
if(POPOUT_REFS['windowInstance']) {
POPOUT_REFS['windowInstance'].close();
}
});
}
focusPopoutWindow() {
POPOUT_REFS['windowInstance'].focus();
}
}
当我单击要在子窗口中呈现的组件中的分离按钮时,它会删除主窗口中的组件,因为它是基于ngIf 呈现的。该组件在新的子组件中运行良好。当我关闭子窗口并再次根据条件重新渲染组件时,即使更改了属性,也不会触发角度变化检测。我必须手动触发更改检测才能使其工作。这是我的MainComponent,我需要手动触发更改检测以反映分离组件中的更改:
import { Component, OnInit, ChangeDetectorRef } from '@angular/core';
import { EventService } from '../service/event.service';
import { PortalService } from '../service/portal.service';
import { ChangeDetectionStrategy } from '@angular/compiler/src/compiler_facade_interface';
@Component({
selector: 'app-main',
templateUrl: './main.component.html',
styleUrls: ['./main.component.css']
})
export class MainComponent implements OnInit {
isAttached: boolean;
num: number;
constructor(
private eventService: EventService,
private portalService: PortalService,
private changeDetectorRef: ChangeDetectorRef
) {
this.isAttached = true;
}
ngOnInit() {
const popoutComponent = this.handlePopoutComponent.bind(this);
this.eventService.numberEvent$.subscribe(val => {
this.num = val;
});
this.eventService.popoutEvent$.subscribe(val => {
if (val != null) {
popoutComponent(val);
}
});
}
handlePopoutComponent(val: boolean) {
this.isAttached = val;
this.changeDetectorRef.detectChanges();
if (this.isAttached === false && !this.portalService.isPopoutWindowOpen()) {
this.portalService.popOutComponent();
}
}
onNumberPublish() {
this.num += 1;
this.eventService.publishNumberEvent(this.num);
}
}
有没有正确的方法来做到这一点?我猜窗口关闭事件不会干净地处理组件并将其重新附加到主窗口。
【问题讨论】:
标签: angular angular-cdk