返回文章列表

Angular FormGroup:響應式表單

11 分鐘
前端Angular

Angular 提供兩種表單處理方式:Template-driven Forms 和 Reactive Forms。

本篇介紹 Reactive Forms (響應式表單),它透過 FormGroupFormControlFormArray 在 TypeScript 中管理表單狀態,讓表單邏輯更容易測試和維護。


FormControl

FormControl 是響應式表單的基本單位,代表一個單一的輸入欄位。

TypeScript
import { Component } from '@angular/core';
import { FormControl, ReactiveFormsModule } from '@angular/forms';

@Component({
  standalone: true,
  imports: [ReactiveFormsModule],
  template: `
    
    

目前值:{{ name.value }}

`, }) export class DemoComponent { name = new FormControl(''); }

讀取與設定值

TypeScript
// 讀取值
console.log(this.name.value);

// 設定值
this.name.setValue('Charmy');

// 部分更新 (FormControl 只有一個值,通常用 setValue)
this.name.patchValue('Charmy');

監聽值的變化

TypeScript
this.name.valueChanges.subscribe(value => {
  console.log(value);
});

FormGroup

FormGroup 將多個 FormControl 組合成一個群組,代表整個表單或表單的一部分。

TypeScript
import { Component } from '@angular/core';
import { FormGroup, FormControl, ReactiveFormsModule } from '@angular/forms';

@Component({
  standalone: true,
  imports: [ReactiveFormsModule],
  template: `
    

表單值:{{ form.value | json }}

`, }) export class RegisterComponent { form = new FormGroup({ name: new FormControl(''), email: new FormControl(''), }); }

讀取與設定值

TypeScript
// 讀取整個表單的值
console.log(this.form.value); // { name: '', email: '' }

// 讀取單一欄位
console.log(this.form.get('name')?.value);

// 設定所有欄位的值
this.form.setValue({
  name: 'Charmy',
  email: 'charmy@example.com',
});

// 部分更新 (只更新指定欄位)
this.form.patchValue({
  name: 'Charmy',
});

表單狀態

TypeScript
this.form.valid   // 是否通過所有驗證
this.form.invalid // 是否有驗證錯誤
this.form.dirty   // 是否有欄位被修改過
this.form.touched // 是否有欄位被觸碰過 (失焦)
this.form.pristine // 是否尚未被修改

驗證

內建驗證器

Angular 的 Validators 提供常用的內建驗證規則:

TypeScript
import { FormGroup, FormControl, Validators } from '@angular/forms';

form = new FormGroup({
  name: new FormControl('', [
    Validators.required,
    Validators.minLength(2),
    Validators.maxLength(50),
  ]),
  email: new FormControl('', [
    Validators.required,
    Validators.email,
  ]),
  age: new FormControl('', [
    Validators.min(0),
    Validators.max(120),
  ]),
});

常用的內建驗證器:

驗證器說明
Validators.required必填
Validators.minLength(n)最少 n 個字元
Validators.maxLength(n)最多 n 個字元
Validators.emailEmail 格式
Validators.min(n)最小值 n
Validators.max(n)最大值 n
Validators.pattern(regex)符合正規表達式

顯示驗證錯誤

HTML
姓名為必填 至少需要 2 個字元

自訂驗證器

自訂驗證器是一個函式,接收 AbstractControl,驗證失敗時回傳錯誤物件,驗證通過時回傳 null

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

function noSpaceValidator(control: AbstractControl): ValidationErrors | null {
  if (control.value && control.value.includes(' ')) {
    return { noSpace: true };
  }
  return null;
}

使用自訂驗證器:

TypeScript
form = new FormGroup({
  username: new FormControl('', [
    Validators.required,
    noSpaceValidator,
  ]),
});

顯示自訂錯誤:

HTML

  使用者名稱不能包含空格

FormArray

FormArray 用來管理數量不固定的表單欄位,例如多個電話號碼、多個項目清單。

TypeScript
import { Component } from '@angular/core';
import { FormGroup, FormControl, FormArray, Validators, ReactiveFormsModule } from '@angular/forms';
import { NgFor } from '@angular/common';

@Component({
  standalone: true,
  imports: [ReactiveFormsModule, NgFor],
  template: `
    
`, }) export class ContactComponent { form = new FormGroup({ phones: new FormArray([ new FormControl('', Validators.required), ]), }); get phones() { return this.form.get('phones') as FormArray; } addPhone() { this.phones.push(new FormControl('', Validators.required)); } removePhone(index: number) { this.phones.removeAt(index); } }

表單提交與重置

提交表單

HTML
TypeScript
onSubmit() {
  if (this.form.valid) {
    console.log(this.form.value);
    // 送出資料...
  }
}

重置表單

TypeScript
// 重置為初始空值
this.form.reset();

// 重置為指定值
this.form.reset({
  name: '',
  email: '',
});

reset 除了清空值,也會重置 dirtytouched 等狀態。


總結

Angular 響應式表單的三個核心類別:

  • FormControl:單一欄位,管理值與驗證狀態
  • FormGroup:多個欄位的群組,代表整個表單
  • FormArray:數量不固定的欄位陣列
FormControlFormGroupFormArray
用途單一輸入表單群組動態欄位
取值.value.value.value
設值setValuesetValue / patchValuepush / removeAt