为什么使用自定义全局验证器时,mat-error 不会显示在 Angular Material 6 中的 mat-form 字段内

问题描述 投票:0回答:5

我正在使用角材料6,我在mat-form-field内有一个验证,当在mat-form-field之后移动到正确显示的mat-error时,不显示mat-error。

无效代码:

 <mat-form-field>
<input matInput type="time" formControlName="ToTime"/> <mat-error *ngIf="DaterForm.get('ToTime').hasError('InValidToTime')">FromTime Should be less than ToTime if choose a same date</mat-error>
     </mat-form-field>

工作正常:

 <input matInput type="time" formControlName="ToTime"/> </mat-form-field>
 <mat-error *ngIf="DaterForm.get('ToTime').hasError('InValidToTime')">FromTime Should be less than ToTime if choose a same date</mat-error>

有人解释了为什么该控件内部不起作用。

现场演示: 堆栈闪电战

angular angular-material2 angular6 angular-material-6
5个回答
41
投票

是的,默认情况下不显示

mat-error
。仅当输入为
touched
时才显示。

但是,幸运的是,您可以使用绑定到

errorStateMatcher
元素的
mat-input
输入属性来覆盖此行为。

添加此功能的拉取请求

用途:

<mat-form-field>
    <input matInput [errorStateMatcher]="matcher" [matDatepicker]="picker" placeholder="Choose a Start date" 
    formControlName="FromDate"
      [min]="minFromDate" 
           [max]="maxToDate" >
    <mat-datepicker-toggle matSuffix [for]="picker" ></mat-datepicker-toggle>
    <mat-datepicker #picker></mat-datepicker>
    <mat-error >Please provide a valid Fromdate</mat-error> 
  </mat-form-field> 

所以你必须以这种方式在你的代码中实现

ErrorStateMatcher

export class MyErrorStateMatcher implements ErrorStateMatcher {
  isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
    const isSubmitted = form && form.submitted;
    return (control && control.invalid);
  }
}

并在您的组件中为

matcher
类添加一个新对象
ErrorStateMatcher
,它将充当
[errorStateMatcher]="matcher"

的值
matcher = new MyErrorStateMatcher();

我还在你的分叉中添加了相同的代码stackblitz

建议

您无需为

ngIf
提供
mat-error
条件来指定您的
formControlName
。将根据它所在的
mat-form-field
自动考虑它。


5
投票

我找到了一个非常简单的解决方案,无需重写 ErrorStateMatcher 类,只需在 app.module.ts 中导入即可

1- 导入库:

import { ErrorStateMatcher, ShowOnDirtyErrorStateMatcher } from '@angular/material/core'; 

2- 添加到提供商,例如:

@NgModule({
  providers: [
    AuthService,
    UserService,
    { provide: ErrorStateMatcher, useClass: ShowOnDirtyErrorStateMatcher }
  ],
})

重新提供应用程序。

Reza Taba

于 2021 年 1 月 2 日更新

上述简短解决方案存在一个问题:如果用户在触摸(模糊)后将字段留空,则不会显示required错误。

请参阅我的解决方案进行修复。


1
投票

全局,在键入或触摸时显示 mat-error: 与提供的解决方案不同,此方法将处理所有 mat 错误,而不需要对每个输入字段应用匹配器。

1- 创建 touched-error-state.matcher.ts 文件:

import {FormControl, FormGroupDirective, NgForm } from '@angular/forms';
import {ErrorStateMatcher} from '@angular/material/core';

export class TouchedErrorStateMatcher implements ErrorStateMatcher {
    isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
        return !!(control && control.invalid && (control.dirty || control.touched));
    }
}

2- 在 app.module 中导入:

import { ErrorStateMatcher } from '@angular/material/core';
import { TouchedErrorStateMatcher } from './your-folder-path/touched-error-state.matcher';

3- 现在将其提供给提供商:

@NgModule({
  providers: [
    AuthService,
    UserService,
    { provide: ErrorStateMatcher, useClass: TouchedErrorStateMatcher }
  ],
})

4- 重新提供应用程序。


0
投票

您可以添加以下功能:

validateAllFormFields(formGroup: FormGroup) {
    Object.keys(formGroup.controls).forEach(field => {
        const control = formGroup.get(field);
        if (control instanceof FormControl) {
            control.markAsTouched({ onlySelf: true });
        } else if (control instanceof FormGroup) {
            this.validateAllFormFields(control);
        }
    });
}

并在 ngOnInit 函数中使用 FormGroup 调用它,如下所示:

    this.validateAllFormFields(this.submittedForm);

0
投票

我遇到了同样的问题,并在做了一些研究后解决了它。我找到了很多解决方案,但它们过于复杂。所以,这就是我的做法。您可以在组件中添加以下代码:

 loginForm: FormGroup;

this.loginForm.get('email')?.valueChanges.subscribe(() => {
  this.loginForm.get('email')?.markAsTouched();
});

我正在使用有角度的形式:

import { FormBuilder, FormGroup, Validators } from '@angular/forms';

上面的代码非常不言自明,但对于那些基本上想要解释的人来说 订阅了 valueChanges observable 以进行电子邮件控制。每当值发生变化时,控件就会被标记为已触摸。 这使得验证错误在用户键入时出现,从而提供即时反馈。 谢谢。希望有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.