Get ViewChildren Template By Id

半城伤御伤魂 提交于 2021-02-08 08:19:27

问题


In my component I get a list of its markup templates by using ViewChildren:

@ViewChildren(TemplateRef) private _templates: QueryList<TemplateRef<unknown>>;

In Angular8 I was not able to filter them by an Id, so i needed to look for an internal property - which was somehow a bit hacky:

let template = this._templates.find(t => (<any>t)._def.references[id]) : null;

Now, with Angular 9, this doesn't work anymore. I checked the object and found a new "hack":

this._templates.find(t => (<any>t)._declarationTContainer?.localNames?.includes(id)) : null;

But is there any new or clean solution for this scenario?

Still hoping for a solution that works without a custom Directive, eg. MatTab probably does something similar, too:

<mat-tab>
    <ng-template mat-tab-label>
        ...
    </ng-template>

    <ng-template matTabContent>
        ...
    </ng-template>
</mat-tab>

回答1:


A clean solution for your scenario is to create a NgTemplateNameDirective directive with ng-template[name] selector:

import { Directive, Input, TemplateRef } from '@angular/core';

@Directive({
  selector: 'ng-template[name]'
})
export class NgTemplateNameDirective {
  @Input() name: string;

  constructor(public template: TemplateRef<any>) { }
}

after that create templates like:

<ng-template name="t1"></ng-template>
<ng-template name="t2"></ng-template>

then query NgTemplateNameDirective instead of TemplateRef:

@ViewChildren(NgTemplateNameDirective) private _templates: QueryList<NgTemplateNameDirective>;

and finally search your template by name

getTemplateRefByName(name: string): TemplateRef<any> {
  const dir = this._templates.find(dir => dir.name === name);
  return dir ? dir.template : null
}

Works fine in both view engines: ViewEngine and Ivy.

Ng-run Example



来源:https://stackoverflow.com/questions/60191471/get-viewchildren-template-by-id

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!