【问题标题】:How to destroy component created dynamically angular 8如何销毁动态创建的组件角度8
【发布时间】:2020-03-01 05:37:03
【问题描述】:

我是 Angular 的新手。我有一个按钮,每次单击它时,它都会动态创建一个组件。我需要每个组件都有一个按钮或可以专门破坏该组件的东西。我在动态组件中有一个功能,当我点击它时,该组件必须关闭,但我不知道如何将它传递给打字稿文件的功能。请帮助我。

app.component.ts

import { Component, OnInit, ComponentFactoryResolver, ViewChild, Input,ComponentRef,ViewContainerRef } from '@angular/core';
import {ChatService} from "./services/chat.service";
import {Mensaje} from "./models/mensaje";
import {ConversacionComponent} from "./components/conversacion/conversacion.component";
import {ConversacionDirective} from "./components/conversacion/conversacion.directive";

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
    providers:[ChatService]
})
export class AppComponent {
    @ViewChild(ConversacionDirective, {static: true}) eldinamico: ConversacionDirective;
  title = 'chat';

  constructor(private cfr: ComponentFactoryResolver){  }
    ngOnInit() { }


    componenteDinamico(mensaje: string) {
        const cf = this.cfr.resolveComponentFactory(ConversacionComponent);
        const vcr = this.eldinamico.viewContainerRef;
        vcr.createComponent(cf, 0);
    }
}

conversacion.directive.ts

import { Directive, ViewContainerRef } from '@angular/core';

@Directive({
    selector: '[appConversacionDinamica]'
})
export class ConversacionDirective {

    constructor(public viewContainerRef: ViewContainerRef) { }

}

app.component.html

<input type="text" #mensaje><br/>
<button (click)="componenteDinamico(mensaje.value)"> Crear Componente </button>
<br/>
<div class="orden">
  <ng-template appConversacionDinamica></ng-template>

</div>

conversacion.component.html


<button (click)="removeObject()">delete me</button>
<div>
    this is a component dynamically
</div>

conversacion.component.ts

import {Component, Input, OnInit, Output, EventEmitter,ViewChild,ElementRef,ComponentRef} from '@angular/core';

@Component({
  selector: 'app-conversacion',
  templateUrl: './conversacion.component.html',
  styleUrls: ['./conversacion.component.css']
})
export class ConversacionComponent implements OnInit {
    mensaje: string;   
    vcr:any; 

  constructor() {}

  ngOnInit() {}   

  removeObject(){
    this.vcr.destroy();
    }
}

【问题讨论】:

    标签: angular angular8


    【解决方案1】:

    下面是动态组件可以“删除自身”的示例。创建者(app.component.ts)订阅动态组件(simple.component.ts)的输出,然后调用.destroy()

    此外,SimpleComponent 必须作为 entryComponent 包含在模块中,因为它是动态创建的。

    Giphy:https://giphy.com/gifs/W2zx2dhNk4znnYFyGT

    示例:


    app.component.html

    <h1>App</h1>
    <button (click)="onClickAdd()">Create</button>
    
    <br>
    <hr>
    <ng-template #componentsContainer></ng-template>
    
    

    app.component.ts

    import {
      Component,
      ViewChild,
      ViewContainerRef,
      ComponentFactoryResolver,
      ComponentRef,
      OnDestroy
    } from '@angular/core';
    import { Subscription } from 'rxjs';
    import { tap } from 'rxjs/operators';
    import { SimpleComponent } from './simple/simple.component';
    
    @Component({
      selector: 'app-root',
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.css']
    })
    export class AppComponent implements OnDestroy {
      @ViewChild('componentsContainer', { read: ViewContainerRef }) container: ViewContainerRef;
      private subs: Subscription[] = [];
    
      ngOnDestroy() {
        // unsubscribe from all on destroy
        this.subs.forEach(sub => sub.unsubscribe());
      }
    
      onClickAdd = () => {
        const factory = this.componentFactoryResolver.resolveComponentFactory(SimpleComponent);
        const component = this.container.createComponent(factory);
    
        component.instance.numberCreated = this.container.length;
    
        // subscribe to component event to know when to delete
        const selfDeleteSub = component.instance.deleteSelf
          .pipe(tap(() => component.destroy()))
          .subscribe();
    
        // add subscription to array for clean up
        this.subs.push(selfDeleteSub);
      }
    
      constructor(private componentFactoryResolver: ComponentFactoryResolver) {}
    }
    
    

    simple.component.html

    <button (click)="deleteSelf.emit()" style="background-color: blue; color: white">delete self</button>
    <p>Dynamic Component</p>
    <p>Number at time of creation: {{ numberCreated }}</p>
    <hr>
    

    simple.component.ts

    import { Component, OnInit, Output, EventEmitter, Input } from '@angular/core';
    
    @Component({
      selector: 'app-simple',
      templateUrl: './simple.component.html',
      styleUrls: ['./simple.component.css']
    })
    export class SimpleComponent implements OnInit {
      @Output() deleteSelf: EventEmitter<void> = new EventEmitter<void>();
      @Input() numberCreated: number;
    
      constructor() { }
    
      ngOnInit() {
      }
    
    }
    

    app.module.ts

    import { BrowserModule } from '@angular/platform-browser';
    import { NgModule } from '@angular/core';
    
    import { AppRoutingModule } from './app-routing.module';
    import { AppComponent } from './app.component';
    import { SimpleComponent } from './simple/simple.component';
    
    @NgModule({
      declarations: [AppComponent, SimpleComponent],
      imports: [BrowserModule, AppRoutingModule],
      providers: [],
      bootstrap: [AppComponent],
      entryComponents: [SimpleComponent]
    })
    export class AppModule {}
    
    

    【讨论】:

    • 我知道你在说什么,但在我的场景中我不知道该怎么做,你能告诉我吗?
    • 天哪,我更新了答案以包含一个工作示例。让我知道这是否有意义。
    • 它的工作原理!,但我在一行上得到一个错误,我只是通过用 ConversacionComponent 和文件路径替换单词 SimpleComponent 完全复制了你的代码。我在 ViewChild 行中收到错误。“类型 {read: ViewContainerRef} 的参数不可分配给 {'read?:any;static;boolean'} 类型的参数 {'read?:any;static;boolean'}Property 'static' is missing in type {read type of ViewContainerRef } 但在类型 {'read?:any;static;boolean'} " 中是必需的
    • 为什么在 {read: ViewContainerRef} 中向我显示 View Child 的行就像一个错误?
    • 嗯,你是从@angular/core 导入ViewChildViewContainerRef 吗?
    猜你喜欢
    • 2015-07-26
    • 1970-01-01
    • 2019-02-18
    • 1970-01-01
    • 1970-01-01
    • 2021-04-26
    • 2020-02-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多