user4328424
user4328424

Reputation:

Angular2 , How to find index of a view inside a viewContianer

Let's say using I have a directive that can load components dynamically in it's viewContianerRef :

@Directive( { selector : '[loader-ref]' } )
export class LoaderDirective {
    constructor ( private cd : ChangeDetectorRef ,
                  private viewContainer : ViewContainerRef ,
                  private componentResolver : ComponentResolver ) {
    }
    getIndexOf(viewRef:ViewRef){

       return this.viewContainer.indexOf(viewRef);
    }
    createComponent ( dialogComponent : { new() : any } ) : Promise<ComponentRef<any>> {
        return this.componentResolver
                   .resolveComponent( dialogComponent )
                   .then( ( componentFactory : ComponentFactory<any> ) => {
                       return this.viewContainer.createComponent( componentFactory );
                   } );
    }
}

My component that should be loaded dynamically :

@Component({
  selector:'my-dynamic-component'
})
export class myDynamicComponent{

   // Is there any way to get this component's ViewRef , or HostView? 


}

And I'm using LoaderDirective to load a component dynamically like this :

My App :

@Component( {
    selector   : 'example' ,
    template:` <button (click)='getIndex()'></button> <div loader-ref></div>`
})
export class ExampleComponent {
    @ViewChild( LoaderDirective ) loaderDirective : LoaderDirective;


    ngOnInit(){
         let waitForChunk = require( 'myDynamicComponent.ts' );
    waitForChunk( ( file ) => {
        this.loaderDirective
            .createComponent( file[ 'default' ] )
            .then( ( componentRef : ComponentRef<any> ) => {
                componentRef.changeDetectorRef.detectChanges();
            } );
    } );

    }


    getIndex(){
         // Here I want to get index of myDynamicComponent which is loaded 
        ////What do I need to do ?   ??
         let index = this.loaderDirective.getIndexOf(what to pass ? )

         console.log('My index is : '+index);

    }
}

This is working , but know my question :

Inside my directive , I have a viewContainerRef , which has a method called indexOf .

This method is supposed to return the index of the loaded component inside the viewContainerRef , but I don't know how it works and how to use it :

Upvotes: 3

Views: 2882

Answers (2)

yurzui
yurzui

Reputation: 214175

I suppose you are looking for hostView property of ComponentRef

loadedView: ViewRef;
...
  this.loaderDirective
    .createComponent(myDynamicComponent)
    .then((componentRef: ComponentRef<any>) => {
      componentRef.changeDetectorRef.detectChanges();
      this.loadedView = componentRef.hostView; <== this line
    });
...
getIndex(){
  let index = this.loaderDirective.getIndexOf(this.loadedView);
  console.log('My index is : '+index);
}

But in your case it will always be equals 0 because you're firing:

this.viewContainer.clear();

See also Plunker Example for angular2 2.0.0

Update1

if you want to have access to view inside the myDynamicComponent directive then you can leverage the following:

@Component({
  selector: 'my-dynamic-component'
})
export class myDynamicComponent {
  public view: ViewRef;
}

...
 this.loaderDirective
    .createComponent(myDynamicComponent)
    .then((componentRef: ComponentRef<any>) => {
      componentRef.changeDetectorRef.detectChanges();
      componentRef.instance.view = componentRef.hostView; <== add this line
    });

I updated Plunker

Update2

You can also to get viewRef this way:

constructor(private injector: Injector) {}

...
var viewRef = this.injector._view.ref;

Plunker

But in this case you will use private propery of Injector. It's bad practice.

Upvotes: 1

Milad
Milad

Reputation: 28590

If you want to get an access to ViewRef inside your component , one possible solution might be :

@Component({
  selector: 'my-dynamic-component'
})
export class myDynamicComponent implements OnInit {
  public view: ViewRef;
  constructor(private _viewContainerRef:ViewContainerRef){

  }

  ngOnInit(){

   console.log('ViewRef',this._viewContainerRef._element.parentView.ref);
 }
}

Looks a bit hacky , but it works.

Upvotes: 0

Related Questions