问题
I'm new to Angular. I have a button that every time I click it, it creates a component dynamically. I need each component to have a button or something that can destroy that component specifically. I have a function in the dynamic component that when I click on it, that component must be closed, but I don't know how to pass it to the function of the typescript file.Please help me.
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();
}
}
回答1:
Below is an example where the dynamic component can "delete itself". The creator (app.component.ts) subscribes to the output of the dynamic component (simple.component.ts) and then invokes .destroy().
Also, the SimpleComponent has to be included in the module as an entryComponent since it is created dynamically.
Giphy: https://giphy.com/gifs/W2zx2dhNk4znnYFyGT
Example:
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 {}
来源:https://stackoverflow.com/questions/58701297/how-to-destroy-component-created-dynamically-angular-8