如何将程序化创建的ComponentRef正确传入Angular Material mat-stepper?
解决方案:将程序化创建的组件挂载到Mat-Step中
你不需要用ngTemplateOutlet,因为你已经通过ViewContainerRef.createComponent生成了完整的组件实例(ComponentRef),直接把组件的宿主视图挂载到mat-step对应的容器里就行,步骤如下:
1. 模板层:为每个Mat-Step添加容器占位符
在封装mat-stepper的组件模板里,给每个mat-step内部加一个<ng-template>作为容器,并用模板引用变量标记:
<mat-vertical-stepper> <mat-step *ngFor="let _ of componentRefs; let i = index"> <!-- 可选:设置step的标题 --> <ng-template matStepLabel>步骤 {{i + 1}}</ng-template> <!-- 用来挂载组件的容器 --> <ng-template #stepContainer></ng-template> </mat-step> </mat-vertical-stepper>
2. 组件类:获取容器并挂载组件实例
通过@ViewChildren获取所有stepContainer对应的ViewContainerRef,然后在视图初始化后(或组件数组更新时),将每个ComponentRef的宿主视图插入到对应容器中:
import { Component, Input, ViewChildren, QueryList, ViewContainerRef, AfterViewInit, OnChanges, SimpleChanges } from '@angular/core'; import { ComponentRef } from '@angular/core'; @Component({ selector: 'app-stepper-wrapper', templateUrl: './stepper-wrapper.component.html' }) export class StepperWrapperComponent implements AfterViewInit, OnChanges { @Input() componentRefs: ComponentRef<any>[] = []; @ViewChildren('stepContainer', { read: ViewContainerRef }) private stepContainers!: QueryList<ViewContainerRef>; ngAfterViewInit(): void { this.mountComponentsToSteps(); } ngOnChanges(changes: SimpleChanges): void { // 如果componentRefs数组更新,重新挂载组件 if (changes['componentRefs']) { this.mountComponentsToSteps(); } } private mountComponentsToSteps(): void { if (!this.stepContainers || this.componentRefs.length === 0) return; // 先清空所有容器的旧内容 this.stepContainers.forEach(container => container.clear()); // 遍历容器和组件实例,一一对应挂载 this.stepContainers.forEach((container, index) => { const compRef = this.componentRefs[index]; if (compRef) { // 将组件的宿主视图插入到当前step的容器中 container.insert(compRef.hostView); } }); } }
关键说明
ComponentRef.hostView就是组件渲染后的宿主视图,直接插入ViewContainerRef就能完成挂载,不需要额外处理模板。- 实现
OnChanges是为了处理componentRefs异步更新的场景(比如父组件动态加载组件后传入数组)。 - 每次更新前调用
container.clear()可以避免重复挂载旧组件实例。
内容的提问来源于stack exchange,提问作者L. Kvri
相关产品推荐
相关产品推荐

