Angular中如何获取浏览器原生HTML校验错误信息用于响应式表单
实现方案
核心思路是通过获取表单控件的原生DOM实例,调用浏览器自带的ValidityState校验逻辑和validationMessage属性获取原生错误信息,同时和Angular的表单校验状态做映射同步。
第一步:调整模板代码
首先你需要给表单添加ngNativeValidate属性(Angular 6+支持),关闭Angular默认自动添加novalidate的行为,同时给每个输入框添加和Angular校验器规则一致的原生校验属性,以及模板引用变量方便获取DOM实例:
<form [formGroup]="testForm" #myForm="ngForm" ngNativeValidate> <input type="text" formControlName="city" #cityInput required minlength="3" > <div class="errors" *ngIf="testForm.get('city')?.invalid && testForm.get('city')?.touched"> <!-- 注意Angular的*ngFor要用of,遍历对象需要加keyvalue管道 --> <p *ngFor="let error of testForm.get('city')?.errors | keyvalue"> {{ getNativeErrorMessage(cityInput, error.key) }} </p> </div> </form>
第二步:组件类实现逻辑
在组件中维护Angular校验错误码和原生ValidityState属性的映射表,实现获取原生错误信息的方法:
import { Component } from '@angular/core'; import { FormGroup, FormBuilder, Validators } from '@angular/forms'; @Component({ selector: 'app-test-form', templateUrl: './test-form.component.html', styleUrls: ['./test-form.component.css'] }) export class TestFormComponent { testForm: FormGroup = this.fb.group({ postCode: [{ value: 'postcode', disabled: true }], name: ['John'], city: [{ value: 'London', disabled: false }, [Validators.required, Validators.minLength(3)]], }); // Angular错误码和原生ValidityState属性的映射关系 private errorCodeMap: Record<string, string> = { 'required': 'valueMissing', 'minlength': 'tooShort', 'maxlength': 'tooLong', 'email': 'typeMismatch', 'pattern': 'patternMismatch', 'max': 'rangeOverflow', 'min': 'rangeUnderflow' }; constructor(private fb: FormBuilder) {} getNativeErrorMessage(inputEl: HTMLInputElement, errorCode: string): string { // 触发原生校验更新校验状态 inputEl.checkValidity(); const nativeValidityKey = this.errorCodeMap[errorCode]; // 匹配到对应原生校验规则时返回浏览器原生错误信息 if (nativeValidityKey && inputEl.validity[nativeValidityKey as keyof ValidityState]) { return inputEl.validationMessage; } // 未匹配到的自定义校验规则返回兜底提示 return '字段内容不合法'; } }
注意事项
- 输入框上的原生校验属性必须和Angular响应式表单中配置的校验器规则完全一致,避免两边校验结果不匹配
- 原生错误信息的显示语言跟随浏览器系统语言,无需额外做多语言适配
- 如果你使用的Angular版本低于6,删除
ngNativeValidate属性,手动给form标签添加novalidate="false"即可实现相同效果 - 如果不想给每个输入框定义模板引用,也可以通过
document.querySelector按formControlName查找对应DOM元素,稳定性略低于直接传模板引用
内容的提问来源于stack exchange,提问作者Demiro-FE-Architect
相关产品推荐
相关产品推荐

