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

如何在模板驱动表单中使用MatHorizontalStepper的[stepControl]?

模板驱动表单中使用步进器stepControl的解决方案

你提到的这个问题确实很常见——Angular的步进器(Stepper)官方文档里stepControl的示例大多基于响应式表单,但其实模板驱动表单也能实现类似的步骤验证控制,只是需要注意一个关键细节~

为什么直接用[stepControl]="myNgForm"不生效?

因为stepControl期望接收的是AbstractControl类型的实例,虽然模板驱动的NgForm继承自AbstractControl,但步进器的linear模式逻辑里,它更适配响应式表单的FormGroup/FormControl实例,直接传入NgForm对象时,步进器无法正确识别其验证状态,所以会忽略你的配置。

可行的解决方案

1. 指向NgForm的form属性

模板驱动表单的NgForm对象自带一个form属性,这个属性就是对应的FormGroup实例(属于AbstractControl子类),把它传给stepControl就能让步进器正确识别表单验证状态:

<form #myForm="ngForm">
  <mat-stepper [linear]="true">
    <mat-step [stepControl]="myForm.form">
      <!-- 步骤内的表单控件,需设置验证规则 -->
      <label>用户名</label>
      <input name="username" ngModel required>

      <div>
        <button matStepperNext>下一步</button>
      </div>
    </mat-step>

    <mat-step>
      <!-- 后续步骤内容 -->
      <button matStepperPrevious>上一步</button>
      <button>提交</button>
    </mat-step>
  </mat-stepper>
</form>

此时当第一步的表单未通过验证(比如用户名未填写),matStepperNext按钮会自动禁用,符合linear模式的要求。

2. 针对局部控件分组验证

如果不需要验证整个表单,只想验证当前步骤内的部分控件,可以用ngModelGroup创建局部表单组,然后把stepControl指向这个分组的模板引用:

<form #myForm="ngForm">
  <mat-stepper [linear]="true">
    <mat-step [stepControl]="userInfoGroup">
      <!-- 用ngModelGroup分组当前步骤的控件 -->
      <div #userInfoGroup="ngModelGroup" ngModelGroup="userInfo">
        <label>用户名</label>
        <input name="username" ngModel required>

        <label>邮箱</label>
        <input name="email" ngModel email required>
      </div>

      <div>
        <button matStepperNext>下一步</button>
      </div>
    </mat-step>
  </mat-stepper>
</form>

这种方式更灵活,步进器只会检查当前分组内的控件验证状态。

额外注意事项

  • 确保你的表单控件都正确设置了验证规则(比如required、email等),否则表单永远处于valid状态,步进器的控制逻辑不会生效。
  • 如果按钮没有自动禁用,你可以手动在模板中绑定disabled属性,比如[disabled]="!myForm.form.valid",强制控制按钮状态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:45:25