2

I am trying to get the index of a dynamically created component inside ViewContainerRef

I need to get the index so I can destroy the component if I wanted too.

Code Below

@ViewChild('dynamicInsert', { read: ViewContainerRef }) dynamicInsert: ViewContainerRef

componentFactory

constructor(
  private componentFactoryResolver: ComponentFactoryResolver,
  private viewContainerRef: ViewContainerRef,
) { }

ngAfterViewInit() {
  this.componentFactory = this.componentFactoryResolver.resolveComponentFactory(AssetOptionComponent);
}

addAssetOption() {
  const dynamicComponent = <AssetOptionComponent>this.dynamicInsert.createComponent(this.componentFactory).instance
  // how to get index of this dynamically generated component ^^^^
}

Trying to use

this.dynamicInsert.remove(index: number) to destroy component

but I first need the index of the dynamically created component

this.dynamicInsert.indexOf(viewRef: viewRef)

2 Answers 2

6

To get the index you can use indexOf method and hostView property:

const index = this.dynamicInsert.indexOf(dynamicComponent.hostView)

Also note that if you don't specify the index view container will destroy the last component:

  remove(index?: number): void {
    const viewData = detachEmbeddedView(this._data, index);
    if (viewData) {
      Services.destroyView(viewData);
    }
  }

   export function detachEmbeddedView(elementData: ElementData, viewIndex?: number): ViewData|null {
  const embeddedViews = elementData.viewContainer !._embeddedViews;
     if (viewIndex == null || viewIndex >= embeddedViews.length) {
        viewIndex = embeddedViews.length - 1;
     }

So if you have only one component you don't need to pass index.

To remove all components you can use clear method.

Sign up to request clarification or add additional context in comments.

5 Comments

Yep! You can also just store a ref to the component, and a separate ref for the instance. --> ref = this.container.createComponent(component) --> instance = ref.instance --> Then you can just use ref.destroy()
This method does not work for const dynamicComponent = <AssetOptionComponent>this.dynamicInsert.createComponent(this.componentFactory).instance but works for const dynamicComponent = this.dynamicInsert.createComponent(this.componentFactory). Gives an error of Property 'hostView' does not exist on type 'AssetOptionComponent'
Yeah hostView is a property of the underlying ComponentRef<T> object, not of an instance.
Any suggestion on how to get the index of the instance
@locnguyen, view container stores component refs, not instances, that is why it returns component ref. A component instance is just part of component ref. The way I showed is the only correct way
1

If you are looking to destroy the created component you may consider a shortcut by just subscribing to it's observable destroy:

addAssetOption() {
   const dynamicComponent: ComponentRef<any> = this.dynamicInsert.createComponent(this.componentFactory);
     dynamicComponent.instance.destroy.subscribe(() => dynamicComponent.destroy())
}

and then upon removing event, in AssetOptionComponent, call it:

 export class AssetOptionComponent  {
  destroy = new Destroyable();
  delete(){
    this.destroy.delete();
  }
}

export class Destroyable extends Subject<any>{
 delete() {
    this.next();
  } 
}

Working demo

1 Comment

Please see the StackBlitz demo in the updated answer

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.