如何在 angular 9 中动态删除组件? [英] How do I remove a component dynamically in angular 9?
问题描述
我必须创建一个多选过滤器,它可以接受要单击的多选项值,以便优化后端某些 get API 端点的响应.
I have to create a multi select filter that would accept multi option values to be clicked, in order to refine the response of some get API endpoint on the backend.
每当用户点击一个选项时,就会出现一个筹码".组件将动态呈现以了解用户:嘿,您只需通过此过滤结果,以及该过滤器选项"
Whenever a user click on a option, a "chip" component would be dynamically render to aware the user: "hey you just filter the result by this, and that filter option"
在互联网上环顾四周,我发现了这个 stackblitz
Looking around in internet I found this stackblitz
在此代码示例中,我以某种方式理解这一行:
In this code sample I understand that somehow in this lines:
let componentFactory = this.CFR.resolveComponentFactory(ChildComponent);
let childComponentRef = this.VCR.createComponent(componentFactory);
我们在 ViewContainerRef
中插入给定子组件的实例.找到一个有点像这样的对象:
we insert an instance of a given child component inside a ViewContainerRef
. find a object somewhat like this:
_data: Object { renderElement: <!-- -->, componentView: undefined, viewContainer: {…}, … }
_elDef: Object { nodeIndex: 4, bindingIndex: 0, outputIndex: 1, … }
_embeddedViews: Array(5) [ {…}, {…}, {…}, … ] //here
_view: Object { def: {…}, parent: {…}, state: 1036, … }
在 __embeddedViews
对象下动态生成的视图将堆叠起来
where under __embeddedViews
object the dynamically generated views will be stack up
稍后决定删除哪些视图,这个stackblitz的创建者只需获取组件并创建一个ViewContainerRef.indexOf(component)
来获取存储组件的索引并验证动态生成的组件存在于该数组中.然后他/她只是删除调用 this.ViewContainerRef.remove(index);
Later to decide which views will be deleted, the creator of this stackblitz just get the component and make a ViewContainerRef.indexOf(component)
to get the index in which the component is stored and verify that that the dynamically generated component exist in that array. Then he/she just delete the view calling this.ViewContainerRef.remove(index);
有趣的事情,在我的实现中,当我记录我的 ViewContainerRef
我得到这个对象作为响应:
Funny thing, in my implementation when I log my ViewContainerRef
I get this object as response:
_hostTNode: Object { type: 0, index: 23, injectorIndex: 34, … }
_hostView: Array(94) [ ..., {…}, 147, … ]
_lContainer: Array(12) [ <!--
芯片已按预期成功动态添加,但没有 _embeddedViews,因此我无法动态删除它们,因为 ViewContainerRef.indexOf(chip)
将始终返回 -1 作为不,我不知道"没有芯片"这里"请有人能启发我并说明我在这里做错了什么吗?
The chips are successfully added dynamically as expected, but there is no _embeddedViews, so I cannot remove them dynamically because ViewContainerRef.indexOf(chip)
will always return -1 as "no, I don't have a "chip" here"
Please can someone enlighten me and show what I'm doing wrong here?
推荐答案
你有这样的不一致是因为你以错误的方式使用了 ViewContainerRef API.
You have such inconsistency because you're using ViewContainerRef API in a wrong way.
这是indexOf方法的签名:
abstract indexOf(viewRef: ViewRef): number;
此签名在 Angular 更新期间从未改变.
This signature never changed during Angular updates.
您所指的 stackblitz 使用 Angular 6 版本,该版本在底层利用了 ViewEngine,但在您的代码中,您使用的是 Angular 9 及更高版本,其中 Ivy 编译器发挥作用.
The stackblitz you're referring to uses Angular 6 version that leverage ViewEngine under the hood but in your code you're using Angular 9 and above version where Ivy compiler comes into play.
在stackblitz中你有:
In stackblitz you have:
this.VCR.indexOf(componentRef as any);
意味着您传递的是 ComponentRef 实例而不是 ViewRef 实例.它的工作是偶然的,因为 indexOf 方法看起来像:
Meaning that you're passing ComponentRef instance not ViewRef instance. It works by accident because indexOf method looks like:
ViewContainerRef_.prototype.indexOf = function (viewRef) {
return this._embeddedViews.indexOf(viewRef._view);
};
和
ComponentRef._view === ViewRef._view
在 ViewEngine
中.
您应该改为传递 ViewRef
实例:
You should be passing ViewRef
instance instead:
this.VCR.indexOf(componentRef.hostView)
该演示适用于 Ivy(您的特殊情况),但也适用于 ViewEngine.
The demo works with Ivy(your particular case) but it will also work in ViewEngine.
这篇关于如何在 angular 9 中动态删除组件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!