0%

Angular 筆記 - Reactive Form 表單驗證實作

forms

表單驗證最常見的就是在登入或是註冊頁面會使用到,是很實用的一個練習。

需求

  1. 有三個表單欄位,分別為姓名、電話、密碼。
  2. 表單皆為必填。
  3. 表單驗證錯誤皆會有錯誤反饋資訊。
  4. 電話欄位額外條件為最大不可少於 10 碼,最小不可低於 10 碼。
  5. 密碼欄位額外條件是大小寫和數字的組合,以及長度限制。

HTML 架構

validator.component.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<form>
<label>
<p>使用者名稱</p>
<input type="text" />
</label>

<label>
<p>使用者電話</p>
<input type="text" />
</label>

<label>
<p>使用者密碼</p>
<input type="text" />
</label>
</form>

加上 Angular 的指令

首先要使用表單,在 Angular 有內建完整的表單函式庫,只要引入方法就可以使用了。

app.module.ts 引入表單方法。

app.module.ts

引入

1
import { FormsModule, ReactiveFormsModule } from "@angular/forms";

imports:

1
2
FormsModule,
ReactiveFormsModule,

validator.component.ts

先載入表單要使用的元件。

1
2
3
4
5
6
import {
FormBuilder,
FormControl,
FormGroup,
Validators,
} from "@angular/forms";

form 使用指令 formGroup

  1. 在 form 標籤使用屬性繫結formGroup 指令,其變數為 invalidForm
  2. input 中使用 formControlName,其變數為 namephonepassword

validator.component.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<form [formGroup]="invalidForm">
<label>
<p>使用者名稱</p>
<input type="text" formControlName="name" />
</label>

<label>
<p>使用者電話</p>
<input type="text" formControlName="phone" />
</label>

<label>
<p>使用者密碼</p>
<input type="text" formControlName="password" />
</label>
</form>

validator.component.ts

  1. 因為有使用 formControlName,建立一個變數 formName,並建構一個 formControl 的物件,並預設為空值。
  2. 自定義變數 invalidForm 使用 Angular 內建的 FromGroup 的方法。
1
2
formName = new FormControl("");
invalidForm: FormGroup;

用 formBuilder 建構表單內容與條件

validator.component.ts

  1. 在建構式中建立一個私有方法(private),用 formBuilder 這個變數儲存 FormBuilder 的元件。
  2. 使用 creatForm 函式來執行表單的建立。
  3. invalidForm 變數建立一個物件,裡面有 namephonepassword 的預設值。

    建立物件是使用 this.xxxx.group({...}),並不像原生建立物件實字的寫法,但意思是差不多的。

  4. 因為表單要做驗證,所以有使用到 Validators 這個驗證器,後面帶驗證條件。
  5. 驗證寫法先在屬性後用一個中括號,第 0 個位置是初始值,這邊是給予空值,所以給的是空字串,第 1 個欄位為驗證條件。
  6. name:[‘空值’,驗證條件為必填]。
  7. phone:[‘空值’,驗證條件為必填,最大長度為 10 字元,最小長度為 10 字元]。
  8. password:[‘空值’,驗證條件為必填,使用密碼的正規表達式]。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
constructor(private formBuilder: FormBuilder) {}

//* 在網頁渲染前就呼叫 creatForm
ngOnInit(): void {
this.creatForm();
}
//*建立表單
creatForm() {
this.invalidForm = this.formBuilder.group({
name: ['', Validators.required],
phone: [
'',
Validators.compose([
Validators.required,
Validators.maxLength(10),
Validators.minLength(10),
]),
],
password: [
'',
Validators.compose([
Validators.required,
Validators.pattern('(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{8,16}'),
]),
],
});
}

這樣就達到基本的驗證功能了。

用 ngIf 將驗證提示寫在 html 中

雖然完成了基本驗證功能,可是在使用者端還不會看到驗證提示,所以要來加上驗證提示,驗證提示出現在表單下方。

ngIf 判斷如果有填寫才會做驗證的機制。

使用者名稱驗證提示

  1. 使用 Angular form 提供的 controls 的方法,要控制的欄位(namephonepassword) 的狀態如果是 pristine 驗證為不顯示,但有 errors 的狀態為 required

    pristine 的意思是未被改變過的

  2. 顯示要提示的內容。

name

1
2
3
4
5
6
7
8
9
10
11
12
<label>
<p>使用者名稱</p>
<input type="username" formControlName="name" pInputText />
<small
class="p-error"
*ngIf="
!invalidForm.controls.name.pristine &&
invalidForm.controls.name.errors?.required
"
>請填寫姓名</small
>
</label>

phone

  1. 驗證錯誤的地方使用 hasError 的方法來寫,裡面只要放入剛剛在 TS 中寫好驗證條件即可,要是字串的形式才可以。
  2. 因有兩個條件,所以使用兩段來呈現。

    雖然在 TS 的 maxLengthminLength 是用小駝峰的方式撰寫,但在 html 是全部小寫,這部分需要注意一下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<label>
<p>使用者電話</p>
<input type="text" formControlName="phone" pInputText />

<small
class="p-error"
*ngIf="
!invalidForm.controls.phone.pristine &&
invalidForm.controls.phone.errors?.required
"
>請輸入電話</small
>
<small
class="p-error"
*ngIf="
!invalidForm.controls.phone.pristine &&
invalidForm.controls.phone.hasError('maxlength')
"
>電話長度不可大於 10 碼</small
>
<small
class="p-error"
*ngIf="
!invalidForm.controls.phone.pristine &&
invalidForm.controls.phone.hasError('minlength')
"
>電話格式錯誤</small
>
</label>

password
寫法與 namephone 相同。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<label>
<p>使用者密碼</p>
<input type="text" formControlName="password" pInputText />
<small
class="p-error"
*ngIf="
!invalidForm.controls.password.pristine &&
invalidForm.controls.password.hasError('required')
"
>請輸入密碼</small
>
<small
class="p-error"
*ngIf="
!invalidForm.controls.password.pristine &&
invalidForm.controls.password.hasError('pattern')
"
>密碼格式錯誤:至少一個小寫字母,一個大寫字母,或是數字,密碼長度不得小於 8
個字元亦不可超過 16 字元</small
>
</label>

最後給一個送出按鈕就大功告成了

validator.component.html
因按鈕 type 預設為 submit ,避免按下 enter 按鈕將資料送出,所以在 type 要給予 button 的類型。

1
<p-button type="button" (click)="confirm()">確認</p-button>

validator.component.ts
給予事件,當表單為無效 ( invalid ) 的時候寫入回饋提示。

1
2
3
4
5
6
7
8
//todo 送出按鈕
confirm() {
if (this.invalidForm.invalid) {
alert('表單漏填囉!');
} else {
alert('驗證成功');
}
}

補充

本次範例有使用到 primeng 的 UI 套件。

DEMO: https://stackblitz.com/edit/angular-ivy-9jc9ld?embed=1&file=src/app/app.component.html