Angular Material自定义输入验证消息在Mat-Stepper中不显示求助
解决自定义表单控件在Mat-Stepper中调用markAllAsTouched()后错误消息不显示的问题
问题原因
基于ControlValueAccessor实现的自定义控件,未同步父表单的touched状态。当调用form.markAllAsTouched()时,父表单控件状态更新,但自定义控件内部的触摸状态未被触发,导致MatFormField无法识别控件已触摸,错误消息仅在手动触摸控件后才显示。
解决方案
需要在自定义控件中同步父控件的touched状态,确保onTouched回调被正确触发,具体步骤如下:
1. 跟踪自定义控件的触摸状态
在组件类中添加touched属性,并实现markAsTouched()方法统一处理状态更新和回调触发:
touched = false; markAsTouched(): void { if (!this.touched) { this.touched = true; this.onTouched(); } }
2. 订阅父控件的状态变化
在ngOnInit中监听父控件的状态变化,当父控件被标记为touched时,同步触发自身的markAsTouched()方法:
ngOnInit(): void { this.ngControl.statusChanges?.subscribe(() => { if (this.ngControl.touched && !this.touched) { this.markAsTouched(); } }); }
3. 绑定模板事件
确保模板中的输入框绑定blur事件到onBlur()方法(内部调用markAsTouched()):
<input type="text" [(ngModel)]="value" (input)="onInput($event)" (blur)="onBlur()" >
对应的组件方法:
onBlur(): void { this.markAsTouched(); }
完整自定义控件示例代码
import { Component, OnInit, Self } from '@angular/core'; import { ControlValueAccessor, NgControl } from '@angular/forms'; @Component({ selector: 'app-phone-input', templateUrl: './phone-input.component.html' }) export class PhoneInputComponent implements ControlValueAccessor, OnInit { value: string = ''; touched = false; onChange = (value: string) => {}; onTouched = () => {}; constructor(@Self() public ngControl: NgControl) { this.ngControl.valueAccessor = this; } ngOnInit(): void { this.ngControl.statusChanges?.subscribe(() => { if (this.ngControl.touched && !this.touched) { this.markAsTouched(); } }); } writeValue(value: string): void { this.value = value || ''; } registerOnChange(fn: any): void { this.onChange = fn; } registerOnTouched(fn: any): void { this.onTouched = fn; } markAsTouched(): void { if (!this.touched) { this.touched = true; this.onTouched(); } } onBlur(): void { this.markAsTouched(); } onInput(event: Event): void { const inputValue = (event.target as HTMLInputElement).value; this.onChange(inputValue); } }
效果验证
修改完成后,调用this.form.markAllAsTouched()时,自定义控件会同步更新触摸状态,Mat-Stepper中的错误消息会立即显示,无需手动触摸控件。
内容的提问来源于stack exchange,提问作者Arti
相关产品推荐
相关产品推荐

