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

Angular Signal Forms如何实现markAllAsTouched()等效功能?

Angular Signal Forms 提交时标记所有无效字段为已触碰的实现方法

在Angular Signal Forms中,没有像旧版响应式表单那样给FormGroup直接提供markAllAsTouched()方法,但可以通过递归遍历所有表单控件,手动调用每个控件的markAsTouched()方法来实现相同效果。

步骤1:实现递归标记所有控件的辅助函数

这个函数会处理FormControl、FormGroup和FormArray三种类型的控件,确保嵌套的子控件也被标记为已触碰:

import { FormControl, FormGroup, FormArray } from '@angular/forms';

function markAllAsTouched(control: FormControl | FormGroup | FormArray): void {
  if (control instanceof FormControl) {
    control.markAsTouched();
  } else if (control instanceof FormGroup) {
    Object.values(control.controls).forEach(childControl => {
      markAllAsTouched(childControl);
    });
  } else if (control instanceof FormArray) {
    control.controls().forEach(childControl => {
      markAllAsTouched(childControl);
    });
  }
}

步骤2:在提交逻辑中调用该函数

在表单提交的处理函数里,先调用辅助函数标记所有控件为已触碰,再检查表单是否有效:

import { formGroup, formControl, validators } from '@angular/forms';

// 示例表单定义
myForm = formGroup({
  name: formControl('', validators.required),
  email: formControl('', [validators.required, validators.email]),
  address: formGroup({
    street: formControl('', validators.required),
    city: formControl('', validators.required)
  }),
  hobbies: formArray([formControl('', validators.required)])
});

onSubmit(): void {
  // 标记所有控件为已触碰
  markAllAsTouched(this.myForm());
  
  if (this.myForm().valid) {
    // 执行表单提交逻辑
    console.log('表单提交成功', this.myForm().value);
  }
}

步骤3:模板中显示错误提示

和之前的写法类似,通过控件的touched()和invalid()信号来判断是否显示错误:

<form (ngSubmit)="onSubmit()">
  <div>
    <label>姓名:</label>
    <input [formControl]="myForm().controls.name" />
    <span *ngIf="myForm().controls.name.touched() && myForm().controls.name.invalid()">
      姓名为必填项
    </span>
  </div>

  <div>
    <label>邮箱:</label>
    <input [formControl]="myForm().controls.email" />
    <span *ngIf="myForm().controls.email.touched() && myForm().controls.email.invalid()">
      {{ myForm().controls.email.hasError('required') ? '邮箱为必填项' : '请输入有效的邮箱地址' }}
    </span>
  </div>

  <div>
    <label>街道:</label>
    <input [formControl]="myForm().controls.address.controls.street" />
    <span *ngIf="myForm().controls.address.controls.street.touched() && myForm().controls.address.controls.street.invalid()">
      街道为必填项
    </span>
  </div>

  <button type="submit">提交</button>
</form>

你也可以通过定义getter简化模板中的控件访问,避免重复书写myForm().controls:

get nameControl() {
  return this.myForm().controls.name;
}

get emailControl() {
  return this.myForm().controls.email;
}

模板中就可以直接使用nameControl.touched()这样的写法。

内容的提问来源于stack exchange,提问作者Raphaël Balet

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 03:14:52