Valery Kozlov
Valery Kozlov

Reputation: 1577

How to extract ViewContainerRef and ComponentRef in most efficient way?

I work with angular-material mdSidenav and want to programmatically open it and insert custom component.

I use @ViewChild('varName') to extract componentInstance and @ViewChild('varName', {read: ViewContainerRef}) to extract container where I would place my content.

So, my question is - is it possible just 1 @ViewChild and get other info from extracted reference.

Second question - which values allowed for read property ? ElementRef/ViewContainerRef/... ?

Update:

I found, that ViewContainerRef of mdSidenav incorrect container for my component. How to place component.hostView inside mdSidenav hostView?

Upvotes: 3

Views: 4708

Answers (1)

Max Koretskyi
Max Koretskyi

Reputation: 105517

Is it possible just 1 @ViewChild and get other info from extracted reference.

No, you can't specify multiple read types for one property. For example you specify the following in html:

<ng-template mydir #vc></ng-template>

Now it can be read as ElementRef, TemplateRef, ViewContainerRef or MyDirectiveInstance. You can't specify multiple read types because Angular would not know what to return for this node. You have to specify single read type for each query property. And generally you can't get one type from the other. Although both

Which values allowed for read property ? ElementRef/ViewContainerRef/... ?

There are the following types you can get through query:

  • ElementRef
  • TemplateRef
  • ViewContainerRef
  • Provider (Component/Directive instance)

As can be seen from this source code:

export function getQueryValue(
    view: ViewData, nodeDef: NodeDef, queryValueType: QueryValueType): any {
  if (queryValueType != null) {
    // a match
    let value: any;
    switch (queryValueType) {
      case QueryValueType.RenderElement:
        value = asElementData(view, nodeDef.index).renderElement;
        break;
      case QueryValueType.ElementRef:
        value = new ElementRef(asElementData(view, nodeDef.index).renderElement);
        break;
      case QueryValueType.TemplateRef:
        value = asElementData(view, nodeDef.index).template;
        break;
      case QueryValueType.ViewContainerRef:
        value = asElementData(view, nodeDef.index).viewContainer;
        break;
      case QueryValueType.Provider:
        value = asProviderData(view, nodeDef.index).instance;
        break;
    }
    return value;
  }
}

RenderElement points to the native DOM element associated with the view node but it is used internally and AFAIK can't be accessed using query in the component.

Upvotes: 4

Related Questions