Angular组件动态内容分配异常求助:Stage与Executor组件问题
解决Angular步骤组件内容投影异常问题
问题根源
- 内容全部堆积到最后一个步骤:原代码中
ng-content select="[stepDescription]"会将所有匹配的DOM元素移动到每个循环位置,但Angular的内容投影是移动而非复制DOM节点,最终所有描述元素都会被移到最后一个循环的投影位置。 - number变化时内容消失:原逻辑通过
*ngIf="step > number"切换模板,步骤完成时会隐藏包含投影内容的容器,导致描述内容随之消失。
解决方案
1. 创建步骤描述指令
定义指令标记每个步骤的描述模板,方便Stage组件获取对应模板实例:
// step-description.directive.ts import { Directive, TemplateRef } from '@angular/core'; @Directive({ selector: '[stepDescription]' }) export class StepDescriptionDirective { constructor(public templateRef: TemplateRef<any>) { } }
2. 修改Stage组件
通过@ContentChildren获取所有步骤描述指令,提供按索引获取对应模板的方法:
// stage.component.ts import { Component, Input, ContentChildren, QueryList } from '@angular/core'; import { StepDescriptionDirective } from './step-description.directive'; @Component({ selector: 'stage', templateUrl: './stage.component.html' }) export class StageComponent { @Input() numberOfSteps: number; @Input() number: number; @ContentChildren(StepDescriptionDirective) stepDescriptions!: QueryList<StepDescriptionDirective>; get stepsArray(): number[] { return [...Array(this.numberOfSteps).keys()].map(i => i + 1); } getStepDescription(index: number) { // 步骤从1开始,模板索引从0开始,对应关系:index = step - 1 return this.stepDescriptions?.get(index)?.templateRef; } }
3. 更新Stage组件模板
调整模板结构,用ngTemplateOutlet渲染对应步骤的描述模板,确保每个步骤独立显示内容,状态切换时内容不消失:
<!-- stage.component.html --> <div class="step" *ngFor="let step of stepsArray; let i = index;"> <!-- 根据步骤状态渲染对应图标模板 --> <ng-container [ngTemplateOutlet]="step <= number ? done : pending" [ngTemplateOutletContext]="{step: step}"></ng-container> <!-- 渲染当前步骤的描述模板 --> <ng-container *ngIf="getStepDescription(i)" [ngTemplateOutlet]="getStepDescription(i)"></ng-container> </div> <ng-template #pending let-step="step"> <svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg"> <rect [class.completed]="step <= number" width="36" height="36" rx="18" fill="#F3F3F3"/> <text class="body-3" x="50%" y="50%" dominant-baseline="middle" text-anchor="middle" font-size="16" fill="black">{{ step }}</text> </svg> </ng-template> <ng-template #done> <svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg"> <rect x="0.5" y="0.5" width="35" height="35" rx="17.5" stroke="#929292"/> <path d="M24.7373 10L14.5466 20.3769L11.2415 17.0114L8 20.3122L11.3051 23.6777L14.5678 27L17.8093 23.6992L28 13.3224L24.7373 10Z" fill="#28B446"/> </svg> </ng-template>
4. 模块配置
在你的Angular模块中声明并导出StepDescriptionDirective,确保Executor组件可以使用该指令:
// your-module.ts import { NgModule } from '@angular/core'; import { StageComponent } from './stage.component'; import { StepDescriptionDirective } from './step-description.directive'; @NgModule({ declarations: [StageComponent, StepDescriptionDirective], exports: [StageComponent, StepDescriptionDirective] }) export class YourModule { }
效果说明
- 每个步骤会渲染对应索引的描述内容,不再全部堆积到最后一个步骤。
- 当
number值变化时,步骤图标会切换,但描述内容始终保留在对应步骤下方,不会消失。
内容的提问来源于stack exchange,提问作者Alexandr Boroshenko
相关产品推荐
相关产品推荐

