Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
2.4k views
in Technique[技术] by (71.8m points)

javascript - How do I remove a component dynamically in angular 9?

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"

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);

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, … }

where under __embeddedViews object the dynamically generated views will be stack up

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);

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) [ <!-- 

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You have such inconsistency because you're using ViewContainerRef API in a wrong way.

Here's the signature of indexOf method:

abstract indexOf(viewRef: ViewRef): number;

This signature never changed during Angular updates.

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.

In stackblitz you have:

this.VCR.indexOf(componentRef as any);

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);
};

and

ComponentRef._view === ViewRef._view in ViewEngine.

You should be passing ViewRef instance instead:

this.VCR.indexOf(componentRef.hostView)

Forked Stackblitz

The demo works with Ivy(your particular case) but it will also work in ViewEngine.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...