【发布时间】:2020-07-04 16:09:26
【问题描述】:
我可以动态创建多个组件,并且我希望能够通过单击每个组件上的按钮来分别删除每个组件。我有一个工作演示项目,我尽可能简单。 请看我的stackblitz。您可以通过多次单击创建按钮来创建多个组件。这就是我希望它工作的方式。但是,我希望有一个更简单的方法。 这里是 app.component.ts
import {
Component,
ViewChild,
ComponentFactoryResolver,
ViewContainerRef,
ComponentRef,
OnDestroy
} from "@angular/core";
import { DynamicComponent } from "./dynamic/dynamic.component";
@Component({
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent implements OnDestroy {
private _count = 0;
componentRef: ComponentRef<DynamicComponent>;
dynamics: Map<string, ComponentRef<DynamicComponent>> = new Map();
@ViewChild("viewcontainer", { read: ViewContainerRef, static: false })
viewContainerRef: ViewContainerRef;
constructor(private resolver: ComponentFactoryResolver) {}
createComponent() {
this._count++;
const factory = this.resolver.resolveComponentFactory(DynamicComponent);
this.componentRef = this.viewContainerRef.createComponent(factory);
this.componentRef.instance.name = " " + this._count;
this.dynamics.set(this.componentRef.instance.name, this.componentRef);
this.componentRef.instance.deleteName.subscribe(
name => this.destroyComponent(name),
error => console.log(error)
);
}
destroyComponent(name: string) {
if (this.dynamics.has(name)) {
this.dynamics.get(name).destroy();
}
this.dynamics.delete(name);
}
ngOnDestroy() {
this.dynamics.forEach(
(value: ComponentRef<DynamicComponent>, key: string) => {
value.instance.deleteName.unsubscribe();
}
);
this.dynamics = null;
}
}
这里是 app.component.html
<button (click)="createComponent()">Create a Component</button>
<ng-container #viewcontainer></ng-container>
这里是 dynamic.component.ts
import { Component, Input, Output, EventEmitter } from "@angular/core";
@Component({
selector: "app-dynamic",
templateUrl: "./dynamic.component.html",
styleUrls: ["./dynamic.component.css"]
})
export class DynamicComponent {
@Input() name: string;
@Output() deleteName = new EventEmitter<string>();
constructor() {}
delete() {
this.deleteName.emit(this.name);
}
}
这里是dynamic.component.html
<div>
{{ name }} <button (click)="delete()">Delete</button>
</div>
我在 app.module.ts 中添加了以下行
entryComponents: [DynamicComponent]
我的问题:有没有更简单的方法?可以使用@ViewChildren 吗?像什么?
@ViewChildren(DynamicComponent) dynamics: QueryList<DynamicComponent>;
编辑: 睡了一夜之后,我有了另一个想法。为什么不让每个动态组件都持有对其自身的引用。请看我的第二个stackblitz。该项目不使用地图来保存所有动态的所有 ComponentRef。我只是在每个 DynamicComponent 中保存一个 ComponentRef。但是,它会引发错误。
DynamicComponent_Host.ngfactory.js? [sm]:1 ERROR RangeError: Maximum call stack size exceeded
at callWithDebugContext (services.ts:636)
at Object.debugDestroyView [as destroyView] (services.ts:355)
at ViewRef_.destroy (refs.ts:284)
at ComponentRef_.destroy (refs.ts:122)
at DynamicComponent.ngOnDestroy (dynamic.component.ts:20)
at callProviderLifecycles (provider.ts:575)
at callElementProvidersLifecycles (provider.ts:541)
at callLifecycleHooksChildrenFirst (provider.ts:529)
at destroyView (view.ts:511)
at callWithDebugContext (services.ts:630)
我不明白为什么我的第二个项目不起作用。第一个(在此处的顶部)有效。
编辑:我找到了How to let a component delete itself on a button click with in angular
我想这会比使用 ComponentFactoryResolver 容易得多。
编辑:我在 How to destroy component created dynamically angular 8
找到了类似的问题和解决方案
编辑:我刚刚找到What is the proper use of an EventEmitter? 所以,猜猜我的第一个项目滥用了EventEmitter?
【问题讨论】:
标签: angular