Draftsman
Draftsman

Reputation: 333

Angular get viewContainerRef of ViewRef

i have a definition of templates in my angular app:

<div class="wrapper" grid [data]="data">
  <div class="cell" *cellDef="let cell">{{cell.id}}</col>
  <div class="row" *rowDef="let row"></div>
</div>

Right now I create "rows" in a directive based on some data injected to wrapper. I create for example 10 rows by creating embeddedViews with templateRef and viewContainerRef of rowDef.

Same for cells, but I want to render cells inside of the rows viewRef. My problem right now is, that I am not able to get the viewContainerRef of the embedded TR Element created by rowDef.

Attaching another directive (non-strucural) let me inject the viewContainerRef, but it only gave me the viewContainerRef where the tr is rendered. How can I get the viewContainerRef inside the tr element to attach the cells to?

<div class="row" *rowDef="let row"  non-structural-directive></div>

@Directive({selector: '[non-structural-directive]'})
export class NonStructuralDirective {
  // points to "wrapper" instead of "row" so it isn't helpful at all
  constructor(vc:ViewContainerRef)
}

Upvotes: 2

Views: 1988

Answers (1)

Draftsman
Draftsman

Reputation: 333

For those interested into the solution...

In the end it was really simple and already solved by cdk-table. So it was not my solution neither my idea. (By the way, it is simply brilliant how it was designed)

I've created a component which uses my non-structural-directive as selector. Also I used an ng-container with another directive where I can get the viewContainerRef when it gets rendered.

/**
 * this is the missing piece. You can use components 
 * to select directives and html tags and add html to it.
 * by adding ng-container with another directive we are 
 * now able to reference viewContainerRef of the inner 
 * tr element
 */
@Component({
  selector: 'non-structural-directive, tr[non-structural-directive]',
  template: '<ng-container outlet>/<ng-container>'
})
export class StructuralComponent {}


/**
 * will be created after tr was embedded 
 * provides handle for referencing viewContainerRef inside of tr element
 */
@Directive({
  selector: 'outlet'
})
export class OutletDirective {
  static lastCreatedViewContainerRef:ViewContainerRef;
  constructor(vc:ViewContainerRef) {
    OutletDirective.lastCreatedViewContainerRef = vc;
  }
}

For the Outlet Directive it is important to provide a static variable to store the latest created viewContainerRef, otherwise I will not know where it belongs to. If someone needs further explaination, feel free to respond, I will extend my answer.

Upvotes: 1

Related Questions