locnguyen
locnguyen

Reputation: 841

Angular, Get Index Of Dynamically Created Component Inside ViewContainerRef

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)

Upvotes: 2

Views: 3619

Answers (2)

Vega
Vega

Reputation: 28738

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

Upvotes: 1

Max Koretskyi
Max Koretskyi

Reputation: 105517

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.

Upvotes: 6

Related Questions