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?
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)
The demo works with Ivy(your particular case) but it will also work in ViewEngine.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.