You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Material的自定义Tab组元素:如何访问Slot中的Template?

Nice approach using templates for dynamic tabs—let's get this working for you! Since you're using Angular (with Material's mat-tab-group), accessing projected templates requires using Angular's content querying APIs instead of trying to read slot content directly. Here's how to do it properly:

1. Use Angular's <ng-template> (Idiomatic Approach)

First, switch from native <template> to Angular's <ng-template>—this plays nicer with Angular's template system. We'll also add a custom directive to each template to track its label and content:

<my-tabgroup>
  <ng-template appTab label="Tab 1">
    <p>Tab 1 content</p>
  </ng-template>
  <ng-template appTab label="Tab 2">
    <p>Tab 2 content</p>
  </ng-template>
  <ng-template appTab label="Tab 3">
    <p>Tab 3 content</p>
  </ng-template>
</my-tabgroup>

2. Create a Tab Directive

This small directive will attach to each <ng-template> to capture the tab label and expose the template reference:

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

@Directive({
  selector: '[appTab]'
})
export class TabDirective {
  @Input() label!: string;

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

3. Query Projected Templates in Your my-tabgroup Component

Use @ContentChildren to fetch all instances of the TabDirective in your component's projected content. Then render each tab using ngTemplateOutlet to inject the template content:

import { Component, ContentChildren, QueryList, AfterContentInit } from '@angular/core';
import { TabDirective } from './tab.directive';

@Component({
  selector: 'my-tabgroup',
  template: `
    <mat-tab-group>
      <mat-tab *ngFor="let tab of tabs" [label]="tab.label">
        <ng-container [ngTemplateOutlet]="tab.templateRef"></ng-container>
      </mat-tab>
    </mat-tab-group>
  `
})
export class MyTabgroupComponent implements AfterContentInit {
  @ContentChildren(TabDirective) tabs!: QueryList<TabDirective>;

  ngAfterContentInit() {
    // This lifecycle hook ensures projected content is loaded
    console.log('Loaded tabs:', this.tabs);
  }
}

4. If You Need to Stick with Native <template>

If you must use the native <template> element, you can query them as DOM elements and convert them to Angular TemplateRefs:

Update your markup to add a template reference to each native template:

<my-tabgroup>
  <template #tabTemplate label="Tab 1">
    <p>Tab 1 content</p>
  </template>
  <template #tabTemplate label="Tab 2">
    <p>Tab 2 content</p>
  </template>
</my-tabgroup>

Then adjust your component code to handle native templates:

import { Component, ContentChildren, ElementRef, QueryList, AfterContentInit, ViewContainerRef, TemplateRef } from '@angular/core';

@Component({
  selector: 'my-tabgroup',
  template: `
    <mat-tab-group>
      <mat-tab *ngFor="let tab of tabGroups" [label]="tab.label">
        <ng-container [ngTemplateOutlet]="tab.template"></ng-container>
      </mat-tab>
    </mat-tab-group>
  `
})
export class MyTabgroupComponent implements AfterContentInit {
  @ContentChildren('tabTemplate') nativeTemplates!: QueryList<ElementRef<HTMLTemplateElement>>;
  tabGroups: { label: string; template: TemplateRef<any> }[] = [];

  constructor(private viewContainerRef: ViewContainerRef) { }

  ngAfterContentInit() {
    this.nativeTemplates.forEach(templateEl => {
      const label = templateEl.nativeElement.getAttribute('label');
      // Convert native template to Angular-compatible TemplateRef
      const templateRef = this.viewContainerRef.createEmbeddedView(templateEl.nativeElement).templateRef;
      this.tabGroups.push({ label, template: templateRef });
    });
  }
}

Key Notes

  • @ContentChildren is Angular's way of accessing content projected into your component—this replaces native slot access for Angular-specific use cases.
  • ngTemplateOutlet is how you render Angular templates dynamically, which is perfect for injecting your tab content into each mat-tab.

内容的提问来源于stack exchange,提问作者Andrew

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 14:03:10