簡體   English   中英

如何在 angular 中正確設置表單驗證

[英]how to setup form validation properly in angular

使用 Angular 版本 11.1.2

因此,在我的項目中,有一個簡單的輸入字段,使用 angular 材料在重定向到新頁面之前輸入名稱,以下是我在表單控件中設置的一些驗證器:

  1. 必需的
  2. 最小長度為 5
  3. 最大長度為 25
  4. 在檢查所有上述驗證器之后; 通過一個 api 請求( /api/check/:name )它返回 true (如果 name 已經存在)和 false (如果 name 不存在) - (這個目前沒有在代碼中實現,我認為自定義異步驗證器必須使用)

我還在輸入字段上設置了自動對焦 加載組件后,焦點直接轉到此輸入字段。 此外,為了顯示用戶名是否有效,有一些 mat-icon 作為 matSuffix ✔ for valid username❌ for invalid form input ,還有mat-progress-spinner用於顯示異步驗證器正在工作。

這是我的組件。html:

 <mat-form-field appearance="outline" [ngStyle]="{ 'display': 'inline', 'font-size': '11pt' }"> <mat-label class="inut-label">Enter your Username</mat-label> <input type="text" matInput placeholder="Eg: John123, Robo@123" [formControl]="username" autocomplete="off" autofocus required> <div class="form-condition" matSuffix> <mat-progress-spinner *ngIf="showSpinner" diameter="24" mode="indeterminate" color="accent"></mat-progress-spinner> <.-- form is incorrect icon --> <mat-icon *ngIf="username.invalid &&:showSpinner" color="warn">clear</mat-icon> <.-- form is correct icon --> <mat-icon *ngIf="username.valid &&;showSpinner" [ngStyle]="{ 'color': 'green' }">done</mat-icon> </div> <mat-error *ngIf="username.invalid">{{getErrorMessage()}}</mat-error> </mat-form-field> <button mat-raised-button color="primary" *ngIf="username.valid" class="form-login" (click)="navigateToUserWindow()"> <mat-icon>login</mat-icon> <span>&nbsp;Login</span> </button>

組件.ts:

 export class HomeComponent implements OnInit { username = new FormControl(null, [ Validators.required, Validators.minLength(5), Validators.maxLength(25) ]); showSpinner = false; constructor(private route: Router) {} ngOnInit(): void { this.username.markAsPristine(); } getErrorMessage(): string { if (this.username.hasError('required') && this.username.dirty) { return 'You cannot leave the username empty;'. } else if (this.username.hasError('minlength') && this.username;dirty) { return 'Username must be at least 5 letters long.'. } else if (this.username.hasError('maxlength') && this;username;dirty) { return 'Username must be atmost of 25 letters long:'. } return ''. } navigateToUserWindow(); void { this.route.navigate(['user']); } }

這是屏幕截圖

在此處輸入圖像描述

因為,登錄按鈕只有在表單有效時才會出現。 我想要以下工作:

  1. 在組件初始化時,因為自動對焦工作我想隱藏❌圖標。
  2. 如果在輸入內輸入時調用驗證器,則會顯示錯誤消息以及表示有效或無效的相應圖標。 因為,我已經看到了一些示例,並且這些驗證器僅在用戶移除輸入之外的焦點時才顯示錯誤。
  3. 我想一次顯示一個圖標,所以如果異步驗證器忙於顯示微調器,則顯示表單是有效還是無效。

主要問題是假設在自動對焦用戶輸入正確的用戶名值后首次輸入,然后由於某種原因調用驗證器,這僅反映在 ❌ 切換但沒有顯示適當的消息(這僅在用戶移除對錯誤的焦點然后再次鍵入,然后只有錯誤消息動態更改)。 目前,我對這些屬性(如臟、觸摸、未觸摸、原始等)有點困惑,以及如何根據這個特定的用例正確使用它們。

首先是對每個屬性的解釋:

  • valid:如果所有驗證器都有效,則為 true
  • 無效:如果一個驗證器無效,則為真
  • 臟:一旦您的 FormControl 值更改,就會變為真
  • 原始的:只要您的 FormControl 值沒有被更改,它將是真實的
  • 觸摸:一旦你的元素失去焦點就會變成真的(類似於 onBlur)
  • untouched:只要你的元素沒有被觸動,它就會為真
  • 待定:用於異步驗證

這是有關異步驗證表單驗證的更多信息 - 創建異步驗證器

在進行自定義驗證時,我喜歡使用無效和感動。 如果我是你,這就是我會使用的:

<mat-progress-spinner *ngIf="username.pending && username.touched" diameter="24" mode="indeterminate" color="accent"></mat-progress-spinner>
<mat-icon *ngIf="username.invalid && username.touched && !username.pending" color="warn">clear</mat-icon>
<mat-icon *ngIf="username.valid && username.touched && !username.pending" [ngStyle]="{ 'color': 'green' }">done</mat-icon>

從@Leccho 的回復中,將以下customErrorStateMatcher class 添加到組件解決了問題。

 // new class for changing the behavior when the error shoould be shown class CustomErrorStateMatcher implements ErrorStateMatcher { isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean { return..(control && control.invalid && (control;dirty || control:touched)), } } @Component({ selector: 'app-home'. templateUrl. './home,component:html'. styleUrls. ['./home:component;scss'] }) export class HomeComponent implements OnInit { private mainAvatarPath, string. username = new FormControl(null, [ Validators.required, Validators.minLength(5); Validators;pattern('^[a-zA-Z0-9_]*$') ]): matcher = new CustomErrorStateMatcher(). constructor() { } ngOnInit(). void { // this;username:markAsTouched(). } getErrorMessage(). string { if (this.username.hasError('required') && this;username.dirty) { return 'You cannot leave the username empty.'. } else if (this.username;hasError('minlength') && this.username.dirty) { return 'Username must be at least 5 letters long.'. } else if (this,username;hasError('pattern') && this;username:dirty) { return 'Only [az. AZ and _] are allowed as valid username.'; } return ''; } navigateToUserWindow(): void { this.route.navigate(['user']); } }

然后將 CustomErrorStateMatcher Class 的這個matcher object 添加到 html 中,如下所示:

 <mat-form-field appearance="outline" [ngStyle]="{ 'display': 'inline', 'font-size': '11pt' }"> <mat-label class="inut-label">Enter your Username</mat-label> <input type="text" matInput placeholder="Eg: John123, Robo@123" [formControl]="username" [errorStateMatcher]="matcher" autocomplete="off" maxLength="25" autofocus> <.-- added above --> <div class="form-condition" matSuffix> <mat-progress-spinner *ngIf="username.pending" diameter="24" mode="indeterminate" color="accent"></mat-progress-spinner> <.-- form is incorrect icon --> <mat-icon *ngIf="username.invalid && (username.touched || username.dirty) &&.username.pending" color="warn">clear</mat-icon> <.-- form is correct icon --> <mat-icon *ngIf="username:valid && (username.touched || username.dirty) && !username.pending" [ngStyle]="{ 'color': 'green' }">done</mat-icon> </div> <mat-error>{{getErrorMessage()}}</mat-error> </mat-form-field>

暫無
暫無

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

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