iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 23
0
Modern Web

Angular - 從零開始系列 第 23

Angular - 從零開始 - Day23 - 表單驗證:Template Driven Form

angular

表單驗證在許多網頁中很常使用到,只要有需要輸入資料的地方,就會有表單,而 Angular 本身就帶有表單驗證的內建函式庫,這次就從比較好入手的範本表單驗證做個筆記。

Angular Form 基本用途

  • 將表單資料進行序列化。
  • 提供初始預設資料。
  • 驗證表單資料。
  • 顯示有幫助的錯誤提示訊息。

進階用途

  • 自訂表單驗證器。
  • 自訂表單控制選項。
  • 動態建立控制選項。

Template Driven Form 基本認識

  • 只能進行 E2E 測試。
  • 需要有 DOM 的存在,因為是直接寫在 HTML 標籤上。
  • 需要 import Module: FormsModule。
  • 可以使用下列指令建立:
    • ngForm
    • ngModel
    • ngModelGroup

匯入 formsModule

app.module.ts 中匯入 FormsModule

import { FormsModule } from "@angular/forms";

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, AppRoutingModule, FormsModule],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}

在 HTML 中加入 ngModel

加入 ngModel 後會產生表單的實體,

<form>
  <label
    >帳號:
    <input type="email" name="userEmail" id="" ngModel />
  </label>
  <br />
  <label
    >密碼:
    <input type="password" name="userPassword" id="" ngModel />
  </label>
</form>

並且會產生對應的 class 可以使用,省去還要另外去想 class 狀態的命名。

  • value 有值
  • valid / invalid 符合驗證 / 不符合驗證
  • pristine / dirty 表單資料沒變動 / 有變動
  • touched / untouched 有觸發 / 沒觸發
  • errors 錯誤

一定要加 name,不然會跳錯。
 依需求用 ngModel 指定 componentmodel

加上範本參考變數名稱

form 標籤中加上範本參考變數,並給予自定義名稱,可以參考這篇,為了檢視輸入資料是否正確,加入 pre 標籤與一個管線元件 json,來觀察 #form 這個範本變數中表單值的變化,這個語法僅於開發時使用,上線前都會移除。

<form #form="ngForm">
  <label>帳號:
    <input type="email" name="userEmail" id="" ngModel>
  </label>
  <br>
  <label>密碼:
    <input type="password" name="userPassword" id="" ngModel>
  </label>
</form>

<pre>{{form.value | json}}</pre> //預覽資料狀況

完成後會看到下方畫面。

pre

自行更改 CSS Class 的變化

Angular 驗證會自己帶有預設的 class,這個方式幫助到團隊開發時,不必另外想新的 className,如這次範例可以看到在未更動表單前在開發人員工具的 class 狀態,如下圖:

formsValid

若有更動則會改變 class 名稱。

formsinvalid

可針對這些狀態設定想要的 CSS 樣式。

輸入預設值

可在表單帶入預設值,透過雙向綁定,即可達到該設定,並可直接回饋在表單內。

<form #form="ngForm">
  <label
    >帳號:
    <input type="email" name="userEmail" id="" [(ngModel)]="myEmail" ngModel />
  </label>
  <br />
  <label
    >密碼:
    <input
      type="password"
      name="userPassword"
      id=""
      [(ngModel)]="myPassword"
      ngModel
    />
  </label>
</form>

並且在 app.module.ts 中把資料先預設好。

import { Component } from "@angular/core";

@Component({
  selector: "app-root",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.scss"],
})
export class AppComponent {
  myEmail = "text@email.com";
  myPassword = "12345678";
}

表單就會出現預設資料

preSetting

驗證訊息

在 HTML 本身有一個標籤是 required 驗證功能,Angular 也一樣有這個標籤功能,另外還有最小長度 minlength, 最大長度 maxlength, 信箱格式驗證 pattern 等標籤功能,只要將這些標籤與條件加入 template 即可。

並且也將要驗證的資訊加上 ngIf 的條件,呈現在該表單下方,將兩個表單內容分別使用 formGroup 獨立出來,表單本身也使用 formControlclassName 做好歸類,未來在設定 CSS 時更方便。

使用範本參考變數將 ngModel 的功能賦予到帳號與密碼的欄位。

<form #form="ngForm">
  <div class="formGroup">
    <label
      >帳號:
      <input
        type="email"
        class="formControl"
        name="userEmail"
        id="email"
        placeholder="請輸入帳號"
        required
        pattern="^[a-zA-Z0-9.!#$%&』*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:.[a-zA-Z0-9-]+)*$"
        #iAccount="ngModel"
        [(ngModel)]="myEmail"
      />
    </label>
  </div>
  <div class="errors" *ngIf="iAccount.errors">
    <p *ngIf="iAccount.errors.required">請輸入帳號</p>
    <p *ngIf="iAccount.errors.pattern">信箱格式錯誤</p>
  </div>
  <br />
  <div class="formGroup">
    <label
      >密碼:
      <input
        type="password"
        class="formControl"
        name="userPassword"
        id="password"
        placeholder="請輸入密碼"
        minlength="6"
        required
        #iPassword="ngModel"
        [(ngModel)]="myPassword"
      />
    </label>
  </div>
  <div class="errors" *ngIf="iPassword.errors">
    <p *ngIf="iPassword.errors.required">請輸入密碼</p>
    <p *ngIf="iPassword.errors.minlength">密碼長度須超過 6 字元</p>
  </div>
</form>

這樣就完成了表單驗證功能。

Demo: https://stackblitz.com/edit/angular-ivy-e71hxv?file=src/app/app.component.html


上一篇
Angular - 從零開始 - Day22 - Pipe 管線元件:date
下一篇
Angular - 從零開始 - Day24 - 響應式表單驗證:Reactive Forms
系列文
Angular - 從零開始25
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言