簡體   English   中英

顯示角度反應形式的錯誤消息的最佳方法,一個表單控制多個驗證錯誤?

[英]Best way to show error messages for angular reactive forms, one formcontrol multiple validation errors?

我根據 angular angular form validation error example的建議方法顯示反應式錯誤消息。

在頁面上顯示錯誤的html代碼:

<div [formGroup]="myForm">
  <div>
<input type="text" formControlName="firstName"/>
<div *ngIf="myForm.controls.firstName.invalid"
    class="alert alert-danger">
    <div *ngIf="myForm.controls.firstName.errors.required">
      This Field is Required.
    </div>
    <div *ngIf="myForm.controls.firstName.errors.maxlength">
      your can enter only 50 characters
    </div>
</div>
  </div>
  <div>
<input type="text" formControlName="lastName"/>
<div *ngIf="myForm.controls.lastName.invalid"
    class="alert alert-danger">
    <div *ngIf="myForm.controls.lastName.errors.required">
      This Field is Required.
    </div>
    <div *ngIf="myForm.controls.lastName.errors.maxlength">
      your can enter only 50 characters
    </div>
</div>
  </div>
  </div>

僅供參考我的組件代碼如下:

this.myForm = this.formBuilder.group({
      firstName:['',[Validators.required,Validators.maxLength(50)]],
      lastName:['',[Validators.required,Validators.maxLength(50)]]
    })

如果您看到上面的代碼,我已經對我的名字和姓氏字段應用了兩個驗證。

為了顯示錯誤消息,我編寫了多個 *ngIf 條件來顯示錯誤消息。

有沒有最好的方法來顯示特定控件的驗證消息而無需編寫多個 *ngIf 條件?因為我一次又一次地使用不同的控件名稱和驗證器名稱編寫相同的代碼來顯示錯誤消息。

我建議有一個名為print-error的組件,它可以處理任何類型的 OOTB 或自定義錯誤。

您可以處理任意數量的錯誤。

打印錯誤.component.ts

import {Component, Input} from '@angular/core';

@Component({
    selector: 'print-error',
    templateUrl: './print-error.component.html',
    providers: []
})
export class PrintError {

    @Input("control")
    control: any;

}

打印錯誤.component.html

<div class="text-danger" *ngIf="control && control.errors && (control.dirty || control.touched)">
     <div *ngIf="control.errors.required"><small>This field is required</small></div>
     <div *ngIf="control.errors.unique"><small>{{control.errors.unique}}</small></div>
     <div *ngIf="control.errors.lessThen"><small>{{control.errors.lessThen}}</small></div>
     <div *ngIf="control.errors.greaterThan"><small>{{control.errors.greaterThan}}</small></div>
     <div *ngIf="control.errors.email"><small>{{control.errors.email}}</small></div>
     <div *ngIf="control.errors.mobile"><small>{{control.errors.mobile}}</small></div>
     <div *ngIf="control.errors.confirmPassword"><small>{{control.errors.confirmPassword}}</small></div>
</div>

用法

 <label for="folder-name">Email</label>
 <input name="email" required   emailValidator #email="ngModel" [(ngModel)]="user.email">
 <print-error [control]="email"></print-error>

處理所有錯誤的更好方法,創建一個單獨的組件error-component

error.component.ts

import { Component, Input } from '@angular/core';
import { AbstractControl, AbstractControlDirective } from '@angular/forms';

@Component({
    selector: 'error-component',
    templateUrl: 'error.component.html',
    styleUrls: ['error.component.scss']
})

export class ErrorComponent {

    errorMsgList: any = [];

    @Input() controlName: AbstractControl | AbstractControlDirective

    errorMessage = {
        'required'  : (params)  => `This field is required`,
        'maxlength' : (params)  => `Maximum ${params.requiredLength} characters are allowed`,
        'minlength' : (params)  => `Minimum ${params.requiredLength} characters are required`,
        'pattern'   : (params)  => `Invalid format`,
        'min'       : (params)  => `Minimum amount should be ₹ ${params.min}`,
        'whitespace': (params)   => `White spaces are not allowed`
    };


    listErrors() {
        if (!this.controlName) return [];
        if (this.controlName.errors) {
            this.errorMsgList = [];
            Object.keys(this.controlName.errors).map( error => {
                this.controlName.touched || this.controlName.dirty ?
                this.errorMsgList.push(this.errorMessage[error](this.controlName.errors[error])) : '';
            });
            return this.errorMsgList;
        }
        else {
            return [];
        }
    }
}

error.component.html

<small class="error-block" *ngFor="let errorMessage of listErrors(); let last=last;">
    {{last ? errorMessage: ''}}
</small>  

用法

<input 
   [type] ="inputObj.mobileNumber.type" 
   id="id1" name="custMobNumber" 
   [(ngModel)]="inputObj.mobileNumber.value" 
   [required]="inputObj.mobileNumber.required" 
   [minlength]="inputObj.mobileNumber.minLength" 
   [maxlength]="inputObj.mobileNumber.maxLength" 
   [pattern]="inputObj.mobileNumber.pattern" 
   class="textbox font-15 full-width">
   <error-component [controlName]="collectionForm.controls['custMobNumber']">
    </error-component>

我一直在研究一個主要形式驅動的企業應用程序,並遇到了同樣的挑戰。 我能確定的最佳解決方案是將所有輸入控件包裝在組件中。 然后處理組件內的驗證顯示。 這允許一致的驗證顯示,而無需在每個表單中多次重復代碼。

字段輸入文本.component.html

    <input [formControl]="formControlItem" [maxlength]="maxlength" [placeholder]="placeholder" #input>
    <span *ngIf="formControlItem.invalid && (formControlItem.dirty || formControlItem.touched)" class="text-danger">
        <span *ngIf="formControlItem.errors.required">This field is required</span>
        <span *ngIf="formControlItem.errors.minlength">This field is too short</span>
        <span *ngIf="formControlItem.errors.maxlength">This field is too long</span>
        <span *ngIf="formControlItem.errors.pattern">Invalid value for this field</span>
    </span>

字段輸入文本組件.ts

    import { Component, OnInit } from '@angular/core';
    import { FormControl } from '@angular/forms';

    @Component({
      selector: 'app-field-input-text',
      templateUrl: './field-input-text.component.html'
    })
    export class FieldInputTextComponent implements OnInit, AfterViewInit {
      @Input() formControlItem: FormControl;
      @Input() maxlength: number;
      @Input() placeholder: string = '';

      constructor() { }

      ngOnInit() {
      }
    }

用法

    <app-field-input-text [formControlItem]="form.controls.username" maxlength="10"></app-field-input-text>

在使用中,您可以看到它節省的空間,而不需要額外的驗證行。 您還可以在一個地方重新格式化所有驗證,而不是觸及每個區域。

主要缺點是不能使用 formControl 或 formControlName 屬性。 我嘗試創建一個自定義 ControlValueAccessor 組件,但這對驗證顯示沒有幫助。

我發現您的問題正在尋找其他人是否找到了更好的方法。 我知道這個答案有點晚了,但希望它有所幫助。

如果它是一個小表格,我通常只使用很多*ngIf 但是,如果您的應用程序幾乎完全是需要驗證的表單,那么上面提到的自定義驗證器指令可能會很有用。

查看源代碼,了解如何設置內置驗證器。 https://github.com/angular/angular/blob/2.0.0-rc.3/modules/%40angular/common/src/forms-deprecated/directives/validators.ts#L104-L124

這是我挖出的一個例子,但我認為對於大多數用例來說這有點矯枉過正。 只需在模板 HTML 中寫一個 *ngIf 行,而不是一個全新的 @Attribute...

https://scotch.io/tutorials/how-to-implement-a-custom-validator-directive-confirm-password-in-angular-2

也許試試這個很棒的包: https ://www.npmjs.com/package/ngx-form-validations

這個包有一個用於錯誤消息的通用字典,取決於錯誤類型。 它的安裝一點也不復雜。

它可以管理您的整個表單,而不僅僅是一個控件。 如果您需要一些額外的擴展,請隨時在 GitHub 上與我聯系。

此外:還有一個演示頁面,您可以在其中輕松檢查其操作,並且還有一個演示項目。 聯系方式可在包裹中找到。

另一種方法是使用*ngFor指令。 但是,此方法存在一些問題,需要提供:

  1. ValidationErrors是一個關聯數組(一個具有 1 個或多個鍵的對象,每個鍵與一些錯誤值相關聯),而*ngFor需要一個可迭代數組。
  2. *ngFor會導致大量重新加載,因此錯誤消息會不斷重新呈現。
  3. 您必須在某些方案上選擇錯誤消息看起來如何讓您的驗證器都符合,因為您的消息不再在 HTML 模板中硬編碼,而是在各種ValidationErrors對象中傳遞。

解決上述問題的一些策略(根據項目的具體情況進行調整):

  1. 我使用實用方法(可能是實用程序類中的靜態方法)將ValidationErrors對象轉換為條目數組(如[ { key: msg } ] )。
  2. 通過向*ngFor中的trackBy:屬性提供自定義“trackBy”函數來解決重新渲染問題。 也許同一個實用程序類中的另一個靜態。
  3. 最簡單的方法是使用TranslatePipe並為每個驗證器錯誤鍵提供翻譯。 (如果設置為具有鍵:值對的對象,則可以將關聯的錯誤數據用作字符串插值參數。)另一種方法是使用與錯誤鍵關聯的錯誤數據將最終字符串存儲在其中,或者翻譯管道鍵。 或其中的一些變體,但這會影響您的錯誤消息標簽的外觀。 在下面的示例中,我選擇將每個錯誤鍵用作翻譯鍵,並將錯誤數據用作插值對象。

將其放入代碼中:

實用類:

import ...

export class MyValidatorUtil {
  ...

  public static getErrors(control: AbstractControl | null): ValidationErrors[] {
    return Object.entries(control?.errors ?? {})
             .map(([key, msg]: [string, any]) => ({ key, msg }));
  }

  public static errorTrack(index: number, err: ValidationErrors): string {
    return err['key'] ?? '';
  }
  ...
}

HTML 模板:

<input type="text" formControlName="myInput" .../>
<div class="alert"
     *ngFor="let err of MyValidatorUtil.getErrors(myFormGrp.get('myInput')); trackBy:MyValidatorUtil.errorTrack">
  {{err['key']}} | translate : {{err['msg']}}
</div>

您需要在組件的 TypeScript中添加一個屬性才能使用模板中的靜態函數:

imports ...

export class MyForm {
  public MyValidatorUtil = MyValidatorUtil; // <-- like this
  public myFormGrp: FormGroup ...

我正在按照建議的角度角度形式驗證錯誤示例方法顯示反應形式錯誤消息。

在頁面上顯示錯誤的html代碼:

<div [formGroup]="myForm">
  <div>
<input type="text" formControlName="firstName"/>
<div *ngIf="myForm.controls.firstName.invalid"
    class="alert alert-danger">
    <div *ngIf="myForm.controls.firstName.errors.required">
      This Field is Required.
    </div>
    <div *ngIf="myForm.controls.firstName.errors.maxlength">
      your can enter only 50 characters
    </div>
</div>
  </div>
  <div>
<input type="text" formControlName="lastName"/>
<div *ngIf="myForm.controls.lastName.invalid"
    class="alert alert-danger">
    <div *ngIf="myForm.controls.lastName.errors.required">
      This Field is Required.
    </div>
    <div *ngIf="myForm.controls.lastName.errors.maxlength">
      your can enter only 50 characters
    </div>
</div>
  </div>
  </div>

僅供參考以下我的組件代碼:

this.myForm = this.formBuilder.group({
      firstName:['',[Validators.required,Validators.maxLength(50)]],
      lastName:['',[Validators.required,Validators.maxLength(50)]]
    })

如果您看到上面的代碼,則對我的firstName和lastName字段應用了兩個驗證。

為了顯示錯誤消息,我編寫了多個* ngIf條件來顯示錯誤消息。

是否有任何最佳方式來顯示特定控件的驗證消息而無需編寫多個* ngIf條件?,因為我用相同的代碼一次又一次地編寫相同的代碼,但使用了不同的控件名稱和驗證者名稱來顯示錯誤消息。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM