Template-driven Form 表單驗證
內建驗證屬性
Angular 提供多種內建的驗證屬性,可以直接加在表單元素上:
<input id="email" type="email" name="email" ngModel required email />
常用的驗證屬性包括:
required
- 必填欄位email
- 必須是有效的電子郵件格式minlength="數字"
- 最小長度maxlength="數字"
- 最大長度pattern="正則表達式"
- 符合指定的正則表達式模式
驗證的工作方式
重要的是,這些驗證屬性不會阻止表單提交,它們只會改變表單的內部狀態,例如將 status
變成 INVALID
。
因此,我們需要在提交方法中手動檢查表單的有效性:
onSubmit(formData: NgForm) {
if (formData.form.invalid) {
return; // 如果表單無效,則不處理提交
}
const enteredEmail = formData.form.value.email;
const enteredPassword = formData.form.value.password;
console.log(enteredEmail, enteredPassword);
}
表單控制項的狀態
每個表單控制項都有以下狀態:
valid/invalid:控制項值是否通過所有驗證規則
touched/untouched:使用者是否與元素互動後離開(如點擊後失焦)
dirty/pristine:使用者是否修改過元素的值
這些狀態可用於判斷何時顯示錯誤訊息,以提供更好的使用者體驗。
存取表單控制項
方法一:使用表單物件
可以透過表單物件存取控制項及其狀態:
@if (form.form.controls['email'].touched &&
form.form.controls['email'].invalid) {
<p class="control-error">Invalid email address.</p>
}
但這種方法有個問題:在表單初始化前,controls
可能未定義,導致錯誤:
ERROR TypeError: Cannot read properties of undefined (reading 'touched')

方法二:使用控制項參考(推薦)
更好的方法是使用模板變數直接引用控制項:
<input
id="email"
type="email"
name="email"
ngModel
required
email
#emailCtrl="ngModel"
/>
#emailCtrl="ngModel"
告訴 Angular 將這個輸入元素的 NgModel 實例存儲在 emailCtrl
變數中。
然後可以使用這個變數來檢查控制項的狀態:
@if (emailCtrl.touched && emailCtrl.invalid) {
<p class="control-error">Invalid email address.</p>
}
根據情境顯示特定錯誤
通常我們會為每個欄位顯示特定的錯誤訊息:
@if (emailCtrl.touched && emailCtrl.dirty && emailCtrl.invalid) {
<p class="control-error">Invalid email address entered.</p>
}
@if (passwordCtrl.touched && passwordCtrl.dirty && passwordCtrl.invalid) {
<p class="control-error">
Invalid password entered - must be at least 6 characters long.
</p>
}
或者可以更進一步,針對特定的錯誤類型顯示不同訊息:
@if (emailCtrl.touched && emailCtrl.invalid) {
@if (emailCtrl.errors?.['required']) {
<p class="control-error">Email is required.</p>
} @else if (emailCtrl.errors?.['email']) {
<p class="control-error">Please enter a valid email address.</p>
}
}
表單狀態的 CSS 類別
Angular 會自動為表單控制項添加 CSS 類別,反映其狀態:
ng-valid
/ng-invalid
- 控制項是否有效ng-touched
/ng-untouched
- 控制項是否被觸摸過ng-dirty
/ng-pristine
- 控制項值是否被修改過
這些類別可以用於樣式設計:
input.ng-invalid.ng-touched {
border: 1px solid red;
background-color: #ffdddd;
}
input.ng-valid.ng-touched {
border: 1px solid green;
background-color: #ddffdd;
}
提交按鈕狀態控制
可以根據表單的有效性控制提交按鈕的狀態:
<button type="submit" [disabled]="form.invalid">Submit</button>
這樣當表單無效時,提交按鈕將被禁用。
常見使用場景和最佳實踐
不要過早顯示錯誤:
通常在使用者與欄位互動後(touched)才顯示錯誤訊息
避免一開始就顯示所有錯誤,這會讓使用者感到困惑
漸進式驗證:
先顯示必填錯誤
當欄位有值後,再顯示格式錯誤
視覺反饋:
使用顏色、圖標等視覺元素指示欄位狀態
考慮無障礙性,不要只依賴顏色來傳達信息
即時驗證:
在使用者輸入時或失焦後立即驗證
提供即時反饋,而不是等到表單提交時
Last updated