首页 > 解决方案 > 将动态对话框组件添加到正文

问题描述

下面我展示了打开单个对话框的机制。我想将其转换为多个对话框 -

我有服务

export class CustomModalService {
  public currentComponent: BehaviorSubject<any> = new BehaviorSubject<any>(null);
  public componentRef: ComponentRef<any>;

  constructor(
    private componentFactoryResolver: ComponentFactoryResolver,
    private appRef: ApplicationRef,
    private injector: Injector,
  ) {}

  public appendModalToBody(componentData: any): void {
    this.componentRef = this.componentFactoryResolver
      .resolveComponentFactory(CustomModalComponent)
      .create(this.injector);
    this.appRef.attachView(this.componentRef.hostView);
    const domElem = (this.componentRef.hostView as EmbeddedViewRef<any>).rootNodes[0] as HTMLElement;
    document.body.appendChild(domElem);
    this.componentRef.instance.data = componentData.data;
    this.currentComponent.next(componentData);
  }

  public close(): void {
    this.appRef.detachView(this.componentRef.hostView);
    this.componentRef.destroy();
  }
}

appendModalToBody 方法将 ModalComponent 组件添加到 body。componentData 参数是这样的:

const componentData = {
  component: Content1Component,
};

模态组件模板:

<div class="dialog-background">
  <se-block class="dialog">
    <se-dialog-header>{{ data?.title }}</se-dialog-header>
    <se-dialog-content><ng-template appCustomModal></ng-template></se-dialog-content>
  </se-block>
</div>

模态组件:

export class ModalComponent implements OnInit {
  @ViewChild(CustomModalDirective, { static: true }) public customModalElement!: CustomModalDirective;
  @Input() public data: any;

  constructor(
    public customModalService: CustomModalService,
    private componentFactoryResolver: ComponentFactoryResolver,
  ) {}

  public ngOnInit(): void {
    this.customModalService.currentComponent.subscribe((componentData: any) => {
      if (componentData) {
        this.loadComponent(componentData);
      }
    });
  }

  public loadComponent(componentData: any): void {
    const componentFactory = this.componentFactoryResolver.resolveComponentFactory(componentData.component);
    const viewContainerRef = this.customModalElement.viewContainerRef;
    viewContainerRef.clear();

    const componentRef = viewContainerRef.createComponent<any>(componentFactory);
    componentRef.instance.data = componentData.data;
  }
}

这里的 loadComponent 方法是将 Content(在 componentData 参数中提供)组件动态添加到模态中。

模态组件的样式:

.dialog-background {
  inset: 0px;
  background-color: black;
  z-index: 500;
  position: fixed !important;
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
}

.dialog {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  background-color: white;
  color: black;
}

指示:

@Directive({
  selector: '[appCustomModal]',
})
export class CustomModalDirective {
  constructor(public viewContainerRef: ViewContainerRef) {}
}

所以,在我的应用程序组件模板中,我有:

<button (click)="openModal" >Open modal</button>

在应用程序组件中,我有:

  public openModal(): void {
    const componentData = {
      component: Content1Component,
    };
    this.modalService.appendModalToBody(componentData);
  }

正如我所说,这是用于打开和关闭单个对话框。我的目标是打开和关闭多个对话窗口。在一个对话框中,您应该可以打开另一个对话框(不关闭第一个对话框),第二个对话框应该与第一个对话框重叠。有人可以帮我吗?我在服务中应该有 BehaviorSubject 和所有打开的对话框。但我不知道如何处理打开和关闭它。

标签: javascriptangularangular-dynamic-components

解决方案


推荐阅读