NgTemplateNameDirective

NgTemplateNameDirective

本文介绍了通过 ID 获取 ViewChildren 模板的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的组件中,我使用 ViewChildren 获得了其标记模板的列表:

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

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

在 Angular8 中,我无法通过 Id 过滤它们,所以我需要寻找一个内部属性 - 这在某种程度上有点笨拙:

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;

现在,使用 Angular 9,这不再起作用.我检查了对象,发现了一个新的黑客":

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?

仍然希望有一个无需自定义指令即可工作的解决方案,例如.MatTab 也可能做类似的事情:

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>

推荐答案

一个干净的解决方案是使用 ng-template[name] 创建一个 NgTemplateNameDirective 指令选择器:

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>) { }
}

之后创建模板,如:

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

然后查询NgTemplateNameDirective而不是TemplateRef:

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

最后按名称搜索模板

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

在两个视图引擎中都能正常工作:ViewEngine 和 Ivy.

Ng-run 示例

这篇关于通过 ID 获取 ViewChildren 模板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-02 03:10