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

Angular响应式表单自定义校验在控件touched时未触发如何解决

问题触发原因

Angular 响应式表单的校验函数仅会在以下场景触发执行:

  • 控件的value值发生变更
  • 手动调用控件的updateValueAndValidity()方法
  • 所在表单提交时

控件的touched、dirty等交互状态的变化,本身不会触发校验函数重新运行。你点击输入框触发blur时,仅更新了控件的touched状态为true,控件值没有发生变化,因此自定义校验器不会执行,内部的判断逻辑自然无法生效。

你配置updateOn: 'blur'未生效的原因是:该配置仅指定值变更后触发校验的时机,若blur时控件值和上一次校验时的取值一致,不会触发校验流程。

解决方案

方案一:将交互状态判断移到视图层(推荐)

这是Angular官方推荐的最佳实践,校验器仅负责对值的合法性做校验,和交互状态解耦,提升校验器的可复用性:

  1. 调整自定义校验器,移除touched判断:
import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms';

export class CustomValidation {
  static customEmailValidation(): ValidatorFn {
    return (control: AbstractControl): ValidationErrors | null => {
      if (control.value.length === 0) {
        console.log(control);
        return {
          customError: {
            hasError: true,
            errorType: 'empty field',
            errorLabel: 'test',
          },
        };
      }
      return null;
    };
  }
}
  1. 在模板展示错误时,再加入touched状态判断:
<form [formGroup]="customForm">
  <input formControlName="customInput" />
  <!-- 仅在控件touched时展示错误 -->
  <span *ngIf="customForm.get('customInput').touched && customForm.get('customInput').hasError('customError')">
    请输入有效内容
  </span>
  <button [disabled]="customForm.invalid">Submit</button>
</form>

方案二:手动触发校验(适配特殊需求)

若确实有业务需要在校验器内基于touched状态做逻辑判断,可以在控件blur时手动触发校验:

  1. 给模板的输入框添加模板引用变量:
<input #customInput formControlName="customInput" />
  1. 组件内监听blur事件,手动调用校验方法:
import { ViewChild, ElementRef } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent implements OnInit, AfterViewInit {
  customForm: FormGroup;
  @ViewChild('customInput') inputEl: ElementRef<HTMLInputElement>;

  constructor(private fb: FormBuilder) {}

  ngOnInit() {
    this.customForm = this.fb.group({
      customInput: [
        '', [Validators.required, CustomValidation.customEmailValidation()],
      ],
    });
  }

  ngAfterViewInit() {
    const control = this.customForm.get('customInput');
    this.inputEl.nativeElement.addEventListener('blur', () => {
      // 手动触发全量校验,此时touched状态已经更新完成
      control.updateValueAndValidity();
    });
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 15:54:04