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

Angular组件动态内容分配异常求助:Stage与Executor组件问题

解决Angular步骤组件内容投影异常问题

问题根源

  1. 内容全部堆积到最后一个步骤:原代码中ng-content select="[stepDescription]"会将所有匹配的DOM元素移动到每个循环位置,但Angular的内容投影是移动而非复制DOM节点,最终所有描述元素都会被移到最后一个循环的投影位置。
  2. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 18:27:00