Reactive Forms 表單驗證

添加驗證器

在 Reactive Forms 中,我們可以在建立 FormControl 時加入驗證器。有兩種方式可以添加驗證器:

方式一:直接傳入驗證器陣列

loginForm = new FormGroup({
  email: new FormControl('', [Validators.required, Validators.email]),
  password: new FormControl('', [Validators.required, Validators.minLength(6)])
});

方式二:使用 configuration object

loginForm = new FormGroup({
  email: new FormControl('', {
    validators: [Validators.required, Validators.email],
  }),
  password: new FormControl('', {
    validators: [Validators.required, Validators.minLength(6)],
    // 也可以加入非同步驗證器
    // asyncValidators: [...]
  }),
});

常用內建驗證器

Angular 提供多種內建驗證器:

  • Validators.required - 必填欄位

  • Validators.email - 必須是有效的電子郵件格式

  • Validators.minLength(n) - 最小長度

  • Validators.maxLength(n) - 最大長度

  • Validators.pattern(regex) - 符合指定的正則表達式模式

  • Validators.min(n) - 最小數值(用於數字輸入)

  • Validators.max(n) - 最大數值(用於數字輸入)

在範本中檢查驗證狀態

我們可以在範本中檢查控制項的狀態,以顯示適當的錯誤訊息:

@if(loginForm.controls.email.touched && loginForm.controls.email.dirty &&
   loginForm.controls.email.invalid){
  <p class="control-error">Please enter a valid email address.</p>
}

這種寫法雖然直接,但過於冗長。我們可以在元件類別中使用 getter 方法來簡化:

get emailIsInvalid() {
  return (
    this.loginForm.controls.email.touched &&
    this.loginForm.controls.email.dirty &&
    this.loginForm.controls.email.invalid
  );
}

get passwordIsInvalid() {
  return (
    this.loginForm.controls.password.touched &&
    this.loginForm.controls.password.dirty &&
    this.loginForm.controls.password.invalid
  );
}

然後在範本中簡化使用:

@if(emailIsInvalid){
  <p class="control-error">Please enter a valid email address.</p>
}

@if(passwordIsInvalid){
  <p class="control-error">Password must be at least 6 characters.</p>
}

檢查特定類型的錯誤

通常,我們需要針對不同類型的錯誤顯示不同的訊息。可以使用 errors 屬性來檢查特定類型的錯誤:

@if(loginForm.controls.email.touched && loginForm.controls.email.invalid){
  @if(loginForm.controls.email.errors?.['required']){
    <p class="control-error">Email is required.</p>
  } @else if(loginForm.controls.email.errors?.['email']){
    <p class="control-error">Please enter a valid email format.</p>
  }
}

同樣,我們可以通過 getter 方法使這個過程更簡潔:

get emailErrors() {
  const control = this.loginForm.controls.email;
  if (control.touched && control.invalid) {
    if (control.errors?.['required']) return 'Email is required.';
    if (control.errors?.['email']) return 'Please enter a valid email format.';
  }
  return null;
}

範本中使用:

@if(emailErrors){
  <p class="control-error">{{ emailErrors }}</p>
}

表單整體驗證

除了檢查個別控制項外,我們也可以檢查整個表單的有效性:

<button type="submit" [disabled]="loginForm.invalid">Login</button>

這會在表單無效時禁用提交按鈕。

驗證狀態的 CSS 類別

和 Template-driven Forms 類似,Angular 也會為 Reactive Forms 的控制項添加以下 CSS 類別:

  • ng-valid / ng-invalid

  • ng-touched / ng-untouched

  • ng-dirty / ng-pristine

可以利用這些類別來設置樣式:

input.ng-invalid.ng-touched {
  border: 1px solid red;
}

input.ng-valid.ng-touched {
  border: 1px solid green;
}

表單驗證的最佳實踐

  1. 使用 getter 方法:簡化範本中的驗證邏輯

  2. 具體的錯誤訊息:針對不同類型的錯誤提供明確的訊息

  3. 禁用提交按鈕:在表單無效時禁用提交按鈕,避免無效提交

  4. CSS 狀態樣式:提供視覺反饋,讓使用者知道輸入的狀態

  5. 考慮使用 FormBuilder:使用 FormBuilder 可以簡化表單建立過程

Last updated