订阅"当前"组件的破坏事件

时间:2018-01-05 01:28:26

标签: angular

我试图订阅组件销毁事件。组件A动态创建组件B并将其插入组件为DOM之外。我想订阅destory事件,以便我可以删除创建的组件。

ComponentRef有一个方便的onDestroy方法,但我找不到一种方法来获取对代表组件A(通常是按照创建)的ComponentRef的引用。

我可以传入一个发射器,在组件A中实现onDestroy并在销毁时向它发出并对此作出反应,但这似乎非常繁琐且烦人,不得不一遍又一遍地做。

编辑:

我最终从另一个角度来看这个。我编写了一个组件来充当中介,使用自己的ViewContainerRef来清理东西。

import {
  ApplicationRef, Component, ContentChild, ContentChildren, EmbeddedViewRef, OnDestroy,
  QueryList,
  TemplateRef, ViewChild,
  ViewContainerRef, ViewEncapsulation
} from '@angular/core';

@Component({
  selector: 'app-modal',
  templateUrl: './modal.component.html',
  styleUrls: ['./modal.component.scss'],
  encapsulation: ViewEncapsulation.None
})
export class ModalComponent implements OnDestroy {
  @ContentChild('title') title: TemplateRef<any>;
  @ContentChild('body') body: TemplateRef<any>;
  @ContentChildren('button') buttons: QueryList<TemplateRef<any>>;
  @ViewChild(TemplateRef) modaltemplate;
  views: EmbeddedViewRef<any>[] = [];

  constructor(private appRef: ApplicationRef, private vcRef: ViewContainerRef) {
  }

  show (context) {
    setTimeout(() => {
      const modalView = this.vcRef.createEmbeddedView(this.modaltemplate);
      const modalTitleView = this.vcRef.createEmbeddedView(this.title, {$implicit: context});
      const modalBodyView = this.vcRef.createEmbeddedView(this.body, {$implicit: context});
      const modalElement = modalView.rootNodes[0];

      this.views.push(modalView, modalTitleView, modalBodyView);

      const titleElement = modalElement.querySelector('.modal-card-title');
      const bodyElement = modalElement.querySelector('.modal-card-body');
      const buttonsElement = modalElement.querySelector('.buttons');

      modalTitleView.rootNodes.forEach(c => {
        titleElement.appendChild(c);
      });

      modalBodyView.rootNodes.forEach(c => {
        bodyElement.appendChild(c);
      });

      this.buttons.forEach(b => {
        const buttonView = this.vcRef.createEmbeddedView(b, {$implicit: context});

        buttonView.rootNodes.forEach(n => {
          if (n.classList.contains('cancel')) {
            n.addEventListener('click', () => this.hide());
          }
          buttonsElement.appendChild(n);
        });
        this.views.push(buttonView);
      });

      document.body.appendChild(modalElement);
    }, 0);
  }

  hide () {
    this.views.splice(0, this.views.length)
      .forEach(v => {
        v.destroy();
      });
  }

  ngOnDestroy(): void {
    this.views.splice(0, this.views.length)
      .forEach(v => {
        v.destroy();
      });
  }
}

用法:

<app-modal #deleteModal>
  <ng-template #title let-data>Are you sure you want to unassign {{data.profile.name}} from {{data.place.name}} {{data.place.shortDescription}}?</ng-template>
  <ng-template #body>Don't worry, you can always reassign them back later.</ng-template>
  <ng-template #button let-data><button class="button is-info" (click)="data.removeStaff(data.place, data.profile)">Unassign Staff</button></ng-template>
  <ng-template #button><button class="button cancel">Cancel</button></ng-template>
</app-modal>

0 个答案:

没有答案