Angular 響應式表單 基礎例子

1、案例需求

表單提交,表單全部校驗成功才能提交,當表單校驗錯誤,表單邊框變紅,同時有錯誤提示信息,有重置功能

2、代碼分析

本案例中使用了響應式表單,響應式表單在表單的校驗方面非常方便

2.1、註冊 ReactiveFormsModule

要使用響應式表單,就要從 @angular/forms 包中導入 ReactiveFormsModule 並把它添加到你的 NgModule 的 imports 數組中。

app.module.ts

imports: [
    BrowserModule,
    AppRoutingModule,
    ReactiveFormsModule
  ]

2.2、使用 FormBuilder 來生成表單控件

當需要與多個表單打交道時,手動創建多個表單控件實例會非常繁瑣。FormBuilder 服務提供了一些便捷方法來生成表單控件。FormBuilder 在幕後也使用同樣的方式來創建和返回這些實例,只是用起來更簡單。

  • 注入 FormBuilder 服務
constructor(
    private fb: FormBuilder
  ) { }
  • 生成表單控件

FormBuilder 提供了一個語法糖,以簡化 FormControl、FormGroup 或 FormArray 實例的創建過程。它會減少構建複雜表單時所需的樣板代碼的數量(new FormControl)。

this.formGroup = this.fb.group({
      name: '',
      age: '',
      sex: ''
    });

2.3、FormGroupDirective

formGroup 是一個輸入指令,它接受一個 formGroup 實例,它會使用這個 formGroup 實例去匹配 FormControl、FormGroup、FormArray 實例,所以模版中的 fromControlName 必須和 formGroup 中的 name 匹配。

<form [formGroup]="formGroup" (ngSubmit)="submit()" novalidate>
  <div class="form-group">
    <label>姓名:</label>
    <input type="text"
      formControlName="name">
      <p>{{nameErrorMessage}}</p>
  </div>
</form>

2.3、表單狀態

每個表單控件都有自己的狀態,共五個狀態屬性,都是布爾值。

  • valid 表單值是否有效
  • pristine 表單值是否未改變
  • dirty 表單值是否已改變
  • touched 表單是否已被訪問過
  • untouched 表單是否未被訪問過

以輸入姓名的表單爲例,只驗證該表單的必填項時。表單先獲取焦點並且輸入姓名,最後移除焦點,每一步表單的狀態如下:

初始狀態
狀態
valid false
pristine true
dirty false
touched false
untouched true
輸入狀態
狀態
valid true
pristine false
dirty true
touched false
untouched true
失去焦點後狀態
狀態
valid true
pristine false
dirty true
touched true
untouched true

2.4、表單校驗

表單驗證用於驗證用戶的輸入,以確保其完整和正確。Angular內置的了一些校驗器,如 Validators.required, Validators.maxlength,Validators.minlength, Validators.pattern,但是不能自定義錯誤提示信息,所以實用性不強,滿足不了業務場景的需求,於是我們可以自定義表單校驗器。

自定義表單校驗器

name-validator.ts

import { AbstractControl, ValidatorFn } from '@angular/forms';

export function nameValidator(): ValidatorFn {
  return (control: AbstractControl): { [key: string]: any } => {

    if (!control.value) {
      return { message: '請輸入必選項' };
    }

    if (control.value.length > 10) {
      return { message: '名稱大於10位了' };
    }

    return null;

  };
}

使用自定義驗證器

app.component.ts

this.formGroup = this.fb.group({
      name: ['', nameValidator()],
      age: ['', ageValidator()],
      sex: ['', sexValidator()]
    });

顯示錯誤提示信息

當頁面初始化的時候不應該顯示錯誤信息,也就是表單touched爲true

// Error
private errorMessage(name): string {
    const control = this.formGroup.controls[name];
    return (control.touched && control.invalid) ? control.errors.message : '';
  }

然而touched只有失去焦點才爲true,在輸入的時候一直爲false。導致在輸入的時候,表單校驗錯誤,卻顯示不了錯誤信息。因此需要再次判斷 dirty 狀態,只要表單值改變,則爲false

private errorMessage(name): string {
    const control = this.formGroup.controls[name];
    return ((control.touched || control.dirty) && control.invalid) ? control.errors.message : '';
  }

2.5、markAsTouched

未對錶單操作時,點擊提交按鈕時,則模擬表單被touched,顯示提示信息

markFormGroupTouched(formGroup: FormGroup) {
    Object.values(formGroup.controls).forEach(item => {
      if (item.controls) {  // 當 formGroup中存在 formGroup 時,遞歸
        this.markFormGroupTouched(item.controls);
      } else {
        item.markAsTouched();
      }
    });
  }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章