【问题标题】:Angular Material - show mat-error on button clickAngular Material - 单击按钮时显示 mat-error
【发布时间】:2018-03-26 11:46:20
【问题描述】:

我正在尝试使用<mat-form-field><mat-error> 进行验证。当用户在不填充的情况下从输入中跳出标签时,这可以正常工作。但是,当我单击按钮时,如何强制显示此错误?我没有使用提交。此外,使用模板驱动的表单。

这是我的代码:

HTML:

<mat-form-field>
    <input matInput placeholder="Due Date" name="dueDate" [(ngModel)]="dueDate" [formControl]="dueDateValidator" required>
    <mat-error *ngIf="dueDateValidator.invalid">Due Date is required for Tasks</mat-error>
</mat-form-field>

TS:

dueDateValidator: FormControl = new FormControl('', [Validators.required]);

【问题讨论】:

标签: angular typescript angular-material


【解决方案1】:

了解如何使用带有自定义ErrorStateMatcher 的表单

如果您希望覆盖此行为(例如,尽快显示错误 因为无效控件是脏的或者当父表单组是 无效),您可以使用 matInput 的 errorStateMatcher 属性。 该属性采用 ErrorStateMatcher 对象的实例。一个 ErrorStateMatcher 必须实现一个方法 isErrorState 获取此 matInput 的 FormControl 以及父表单和 返回一个布尔值,指示是否应显示错误。 (真的 表示应该显示它们,而 false 表示它们 不应该。)

我会创建一个单独的文件,例如 default.error-matcher.ts

/** Error when invalid control is dirty or touched*/
export class MyErrorStateMatcher implements ErrorStateMatcher {
  isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
    return !!(control && control.invalid && (control.dirty || control.touched));
  }
}

然后在TS文件中添加:

matcher = new MyErrorStateMatcher();

然后将输入改为使用匹配器:

<mat-form-field>
    <input matInput placeholder="Due Date" name="dueDate" [(ngModel)]="dueDate" [formControl]="dueDateValidator" [errorStateMatcher]="matcher" required>
    <mat-error *ngIf="dueDateValidator.invalid">Due Date is required for Tasks</mat-error>
</mat-form-field>

【讨论】:

  • 高级:如果您要创建自己的自定义表单控件,[errorStateMatcher]CanUpdateErrorState 界面的一部分
【解决方案2】:

您还可以在单​​击按钮时轻松调用AbstractControl.updateValueAndValidity() 函数。这将再次在相应的 ForControl 上运行验证过程并显示错误(如果有)(基于您的验证器)。

所以,在你的例子中:

    checkForErrorsOnButtonClick(): void {
      dueDateValidator.updateValueAndValidity();
    }

【讨论】:

    【解决方案3】:

    根据 Kyle Pfromer 的帖子,我找到了解决方案(针对同一问题):

    在TS文件中我发现无效表单后添加了StateMatcher,例如。

    if (this.myFormGroup.invalid) {
      this.matcher = new MyErrorStateMatcher();
      return;
    }
    

    在 MyErrorStateMatcher 类中我更改如下:

        return !!(control && control.invalid);
    

    我觉得 Angular Material 无论如何都没有检测到错误令人困惑。

    【讨论】:

      【解决方案4】:

      由于您想在按钮单击时显示 mat 错误,请尝试以下操作: 对于 Angular6 版本:

      1. 导入所需的类
      import { FormControl, FormBuilder, FormGroup } from '@angular/forms';
      
      1. 在您的 component.ts 文件中声明表单控件:
      nameControl = new FormControl('');
      
      1. 在html中添加控件:
      <mat-form-field  style="width: 100%" floatPlaceholder="never">
          <input matInput placeholder="your placeholder text" [formControl]="nameControl" required/>
          <mat-error *ngIf="nameControl.errors?.required">name is required</mat-error>
      </mat-form-field>
      
      1. 将此添加到您的按钮单击事件处理程序:
      this.nameControl.markAsTouched();
      

      检查表单控件的使用方式很重要,第 4 点的“.markAsTouched()”将显示相应表单控件的 mat 错误。

      【讨论】:

      • @Simran '的功能是什么?有错误吗?。必填
      • @DipendraGurung 它检查控件出现的错误是否是“必需的”,如果控件错误是必需的验证,则应该出现错误消息,说明“名称是必需的”类似的错误可以检查模式。
      • 我用过this.nameControl.setErrors({ invalid: true });&lt;mat-error *ngIf="nameControl.hasError('invalid')"&gt;Some error message!&lt;/mat-error&gt;
      【解决方案5】:

      这对我有用。 :) 点击按钮:

      this.nameControl.markAsTouched();
      

      【讨论】:

        【解决方案6】:

        Angular 8 有一个新的表单方法:markAllAsTouched();

        这会将控件/表单和所有后代标记为已触摸!!!

        所以:

        this.form.markAllAsTouched();
        

        是解决办法。

        【讨论】:

          【解决方案7】:

          我为不同的场景提供了 3 种不同的解决方案,请使用适合您的一种。

          • 如果你使用的是表单,那么就这样做

            this.form.markAllAsTouched();
            
          • 如果您需要在表单中影响特定字段,则过滤该 nameControl 并执行

            nameControl.markAsTouched();
            
          • 如果您不使用表单,则为input 元素指定ref 并在ts 文件中初始化变量并执行以下操作,

            @ViewChild('myInputRef') myInputRef; // Initialize the ref of input element
            .
            .
            this.myInputRef.control.markAsTouched()
            

          【讨论】:

          • 如果不使用表单,this.myInputRef.control 返回 undefined。
          • 确保为#myInputRef 指定了“ngModel”。喜欢这个&lt;input #myInputRef="ngModel" [(ngModel)]="value" /&gt;
          【解决方案8】:

          最简单的方法是在模板上单击按钮时调用 markUserNameTouched() 方法,如下所示。我们在 formControl 上使用 markAsTouched()。

          public staffLoginForm: FormGroup;
          ngOnInit(){
          this.staffLoginForm = new FormGroup({
          username: new FormControl(null),
          password: new FormControl(null)});
          
          markUserNameTouched():void{
            this.staffLoginForm.get('username').markAsTouched();
          }
          

          【讨论】:

            【解决方案9】:

            您可以按照“Kyle Pfromer”的建议进行操作,或者在使用表单组时,您可以将元素标记为提交时触摸

            onSubmit(){ this.formName.get('formControlName').markAsTouched(); }
            

            【讨论】:

            • 这个太完美了!
            【解决方案10】:

            全局:在输入或触摸时显示 mat-error: 与提供的解决方案不同,此方法将处理应用程序中的所有 mat-errors,而无需将匹配器应用于每个输入。

            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- 重新提供应用程序。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2021-12-18
              • 2019-06-16
              • 1970-01-01
              • 1970-01-01
              • 2019-12-14
              • 2020-12-07
              • 2020-11-15
              • 1970-01-01
              相关资源
              最近更新 更多