检索与TemplateRef关联的变量的名称

时间:2017-03-03 14:08:45

标签: angular

说我有这个模板:

<div class="main__container">
    <ng-template #test></ng-template>
    <ng-template #test2></ng-template>
</div>

我通过以下方式检索对所有TemplateRef的引用:

@ViewChildren(TemplateRef)
private templates;

对于所有这些,我如何检索相关变量的名称?所以&#34;测试&#34;对于第一个模板和&#34; test2&#34;对于另一个。我绝对不想使用变量,如果可以使用ng-template属性,那就可以了。我尝试使用TemplateRefViewContainerRefElementRef,但每次都会返回对comment元素的引用。

4 个答案:

答案 0 :(得分:1)

我设法使用TemplateRef的私有API来做到这一点。这是我目前使用的功能:

@ContentChildren(TemplateRef) templates: QueryList<TemplateRef<any>>;

getTemplate(id: string): TemplateRef<any> {
    // FIXME: Should not use private API...
    return this.templates ? this.templates.find((template: any) => 
    template._def.references[id]) : null;
}

但这不适用于生产版本,实际上我发现你的帖子正在寻找另一个解决方案,如果我找到某些内容或者向Angular github提交功能请求,我会更新。 与此同时,我认为值得分享。

- 编辑 - 看起来很可能使用结构指令。

  

您将在本指南中了解到,星号(*)是一种方便的符号,字符串是微型语法,而不是通常的模板表达式。 Angular将这种符号放入围绕主机元素及其后代的标记<ng-template>中。每个结构指令都与该模板有所不同。

Link to documentation

- 编辑2 - 好吧,它适用于检索TemplateRef的指令,但是目前我使用id将其注册到服务,我不再使用ViewChildren / ContentChildren了。使用* ngTemplateOutlet指令的My Component然后使用该服务检索TemplateRef。

这是指令源代码:

@Directive({
     selector: '[formeTemplate]'
})
export class FormeTemplateDirective {
    @Input('formeTemplate') templateId;

    constructor(private host: TemplateRef<any>, private service: FormeTemplateService) { }

    ngOnInit() {
        this.service.register(this.templateId, this.host);
    }
}

服务:

@Injectable()
export class FormeTemplateService {
    private templates: Array<FormeTemplate>;

    constructor() {
        this.templates = new Array();
    }

    register(id: string, ref: TemplateRef<any>) {
        this.templates.push(new FormeTemplate(id, ref));
    }

    getTemplateRef(templateId: string) : TemplateRef<any> {
        let template = this.templates.find((template) => template.id === templateId);
        return template ? template.ref : null;
    }
}

答案 1 :(得分:1)

我还必须能够动态设置templateRef。目的是根据动态类型选择模板。

我的解决方案(https://stackblitz.com/edit/angular-dynamic-templateref):


@Directive({
  selector: "[typeTemplate]"
})
export class TypeTemplateDirective {
  @Input()
  typeTemplate: string;

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

@Component({
  selector: "type-template",
  template: `
    <ng-container *ngTemplateOutlet="(template$ | async)"></ng-container>

    <ng-template typeTemplate="typeA">Template for type A</ng-template>
    <ng-template typeTemplate="typeB">Template for type B</ng-template>
  `
})
export class TypeTemplateComponent implements AfterViewInit {
  @ViewChildren(TypeTemplateDirective)
  private typeTemplateDirectives: QueryList<TypeTemplateDirective>;

  @Input()
  set type(newType: string) {
    this.type$.next(newType);
  }

  type$ = new BehaviorSubject<string>(null);
  template$ = this.type$.pipe(
    filter(() => !!this.typeTemplateDirectives),
    map(
      type =>
        this.typeTemplateDirectives.find(
          directive => directive.typeTemplate === type
        ).templateRef
    )
  );

  ngAfterViewInit(): void {
    this.type$.next(this.type$.getValue());
  }
}

因此,当将新类型推入时,将使用正确的模板。

答案 2 :(得分:0)

您可以通过按名称询问模板变量来访问模板变量,如下所示:

 @ViewChildren('test, test2') templates;

这是一个简单的Plunker演示行为。

答案 3 :(得分:0)

我有同样的问题。这个简单的示例说明了我的解决方案:

用法:

<app-my-component [templates]="{ highlight: highlightTemplate, italic: italicTemplate }" [useTemplate]="'highlight'">
    <ng-template #highlightTemplate let-contentRef="contentRef">
        <span class="highlighted-text"><ng-container *ngTemplateOutlet="contentRef"></ng-container></span>
    </ng-template>
    <ng-template #italicTemplate let-contentRef="contentRef">
        <span class="font-italic"><ng-container *ngTemplateOutlet="contentRef"></ng-container></span>
    </ng-template>
</app-my-component>

myComponent模板:

<div class="my-component">
    <ng-template #contentRef>The content which is given to the customTemplate</ng-template>
    <ng-container *ngTemplateOutlet="customTemplate; context: { contentRef: contentRef }" >
    </ng-container>
</div>

类定义:

export class MyComponent {

    @Input() private templates: any = {};
    @Input() private useTemplate: string;

    get customTemplate() {
        return this.templates[this.useTemplate];
    }

}