角度删除动态组件

时间:2019-08-24 11:48:26

标签: javascript angular typescript module

我正在使用Angular动态组件创建动态组件以推送烤面包机(通知程序或通知)

- ComponentFactoryResolve
-  EmbeddedViewRef
-  ApplicationRef
-  ComponentRef
-  Injectable
-  Injector

到目前为止,我所做的是创建要推送的组件并为其提供服务并在模块中注册了组件,它可以很好地推动组件,但是问题是当我尝试删除组件时会出现引用最后推送的组件。

  

toast.component.ts(动态组件)


@Component({
  selector: 'uni-toast',
  template: `
    <div>
      <p (click)="closeToast()">{{ type }}</p>
      <p>{{ msg }}</p>
    </div>
  `,
  styles: []
})
export class ToastComponent implements AfterViewInit {
  @Input() index;
  @Input() type;
  @Input() msg;

  ngAfterViewInit() {}

      constructor(private toaster: ToastService) {}

  closeToast() {
    this.toaster.destroyToast(this.index);
  }
}
  

toast.service.ts

import { ToastComponent } from './toast.component';
import { ToastModule } from './toast.module';
import {
  ComponentFactoryResolver,
  EmbeddedViewRef,
  ApplicationRef,
  ComponentRef,
  Injectable,
  Injector
} from '@angular/core';
@Injectable({
  providedIn: ToastModule
})
export class ToastService {
  toastComponentRef: ComponentRef<ToastComponent>;
  private compIndex = 0;

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

  private createToast() {
    const componentFactory = this.componentFactoryResolver.resolveComponentFactory(
      ToastComponent
    );
    const componentRef = componentFactory.create(this.injector);
    this.appRef.attachView(componentRef.hostView);

    const domElem = (componentRef.hostView as EmbeddedViewRef<any>)
      .rootNodes[0] as HTMLElement;
    document.body.appendChild(domElem);

    this.toastComponentRef = componentRef;
  }

  private bindToastData(type: string, msg: string) {
    this.toastComponentRef.instance.index = this.compIndex++;
    this.toastComponentRef.instance.type = type;
    this.toastComponentRef.instance.msg = msg;
  }

  public destroyToast(index) {
    this.appRef.detachView(this.toastComponentRef.hostView);
    this.toastComponentRef.destroy();
  }

  public toast(type: string, msg: string) {
    this.createToast();
    this.bindToastData(type, msg);
  }
} 
  

app.component.ts

import { Component } from '@angular/core';
import { ToastService } from 'toast';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  constructor(private toast: ToastService) {
    // pushing toasts
    this.toast.toast('Error', 'Invalid Credentials');
    this.toast.toast('success', 'success info');
    this.toast.toast('warn', 'warn info');
  }
} 
  

toast.module.ts

import { NgModule } from '@angular/core';
import { ToastComponent } from './toast.component';

@NgModule({
  declarations: [ToastComponent],
  imports: [],
  exports: [ToastComponent],
  entryComponents: [ToastComponent]
})
export class ToastModule {} 

我希望删除单击的组件。

2 个答案:

答案 0 :(得分:0)

基于此demo,您可以这样做

a && b

我的blog展示了如何销毁动态组件

a & b

答案 1 :(得分:0)

您必须记住,组件.html文件不是实际显示的内容,Angular View Engine(Renderer2)使用它来创建浏览器显示的真实DOM。

这样,如果要从视图中“销毁”组件,可以执行此操作,这样Renderer2将从视图(DOM)中将其删除:

<div *ngIf="false">
    <uni-toast></uni-toast>
</div>

显示烤面包机并以编程方式将其隐藏的解决方案:

  • 使用Toaster Service保留一个布尔值,说明是否应该显示烤面包机
  • 展示您的烤面包机组件的组件应使用此布尔值,以ngIf有条件地显示它。

您的服务还可以保存短信,图标,并且您可以使用可观察对象推送事件。