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

Angular中如何基于TemplateRef列表动态填充ng-container并实现模板切换?

Angular模板分页切换:解决TemplateRef引用错误及实现上下页逻辑

问题根源

你犯了两个关键错误:

  • 错误注入TemplateRef:TemplateRef不是可注入的服务,它是对页面模板元素的引用,必须通过@ViewChild装饰器绑定模板上的#标记来获取。
  • 生命周期时机错误:构造函数执行时,Angular还未完成视图初始化,根本无法获取任何模板引用,必须等到ngAfterViewInit钩子触发后才能访问视图元素。

修正后的完整代码

home.component.html

<div class="template-container">
  <ng-container *ngTemplateOutlet="activeTemplate"></ng-container>

  <!-- 选择服务 -->
  <ng-template #allServices>
    <h3>选择服务页面</h3>
    <button (click)="prevPage()" [disabled]="currentIndex === 0">上一页</button>
    <button (click)="nextPage()" [disabled]="currentIndex === templates.length - 1">下一页</button>
  </ng-template>

  <!-- 选择工作人员 -->
  <ng-template #worker>
    <h3>选择工作人员页面</h3>
    <button (click)="prevPage()" [disabled]="currentIndex === 0">上一页</button>
    <button (click)="nextPage()" [disabled]="currentIndex === templates.length - 1">下一页</button>
  </ng-template>

  <!-- 日历展示 -->
  <ng-template #calendar>
    <h3>日历页面</h3>
    <button (click)="prevPage()" [disabled]="currentIndex === 0">上一页</button>
    <button (click)="nextPage()" [disabled]="currentIndex === templates.length - 1">下一页</button>
  </ng-template>

  <!-- 用户详情 -->
  <ng-template #userDetails>
    <h3>用户详情页面</h3>
    <button (click)="prevPage()" [disabled]="currentIndex === 0">上一页</button>
    <button (click)="nextPage()" [disabled]="currentIndex === templates.length - 1">下一页</button>
  </ng-template>
</div>

home.component.ts

import { Component, VERSION, TemplateRef, ViewChild, AfterViewInit } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css']
})
export class AppComponent implements AfterViewInit {
  name = 'Angular ' + VERSION.full;
  
  templates: TemplateRef<any>[] = [];
  activeTemplate: TemplateRef<any>;
  currentIndex = 0;

  // 通过@ViewChild绑定每个模板的#标记
  @ViewChild('allServices') allServicesTemplate: TemplateRef<any>;
  @ViewChild('worker') workerTemplate: TemplateRef<any>;
  @ViewChild('calendar') calendarTemplate: TemplateRef<any>;
  @ViewChild('userDetails') userDetailsTemplate: TemplateRef<any>;

  ngAfterViewInit(): void {
    // 视图初始化完成后,填充模板数组
    this.templates = [
      this.allServicesTemplate,
      this.workerTemplate,
      this.calendarTemplate,
      this.userDetailsTemplate
    ];
    // 设置初始显示的模板
    this.activeTemplate = this.templates[0];
  }

  // 上一页切换逻辑
  prevPage(): void {
    if (this.currentIndex > 0) {
      this.currentIndex--;
      this.activeTemplate = this.templates[this.currentIndex];
    }
  }

  // 下一页切换逻辑
  nextPage(): void {
    if (this.currentIndex < this.templates.length - 1) {
      this.currentIndex++;
      this.activeTemplate = this.templates[this.currentIndex];
    }
  }
}

关键说明

  • @ViewChild的作用:通过模板上的#标记(如#allServices),Angular会自动将对应的模板实例赋值给类中的变量。
  • ngAfterViewInit钩子:这是Angular生命周期中第一个能访问到已初始化视图元素的钩子,必须在这里完成模板数组的初始化。
  • 分页逻辑:用currentIndex跟踪当前显示的模板位置,点击按钮时更新索引并切换activeTemplate,同时通过[disabled]属性禁用边界状态的按钮(比如第一页的上一页按钮)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 17:40:31