Template-driven Forms vs Reactive Forms

Template-driven Forms คือฟอร์มที่กำหนด logic หลักใน Template ด้วย ngModel ส่วน Reactive Forms คือฟอร์มที่สร้างและควบคุมจาก Component Class เหมาะกับงานซับซ้อนและทดสอบง่ายกว่า

Timeline/ประวัติศาสตร์

%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#fabd2f", "primaryTextColor": "#282828", "primaryBorderColor": "#b57614", "lineColor": "#7c6f64", "secondaryColor": "#83a598", "tertiaryColor": "#b8bb26", "background": "#fbf1c7", "mainBkg": "#ebdbb2", "fontFamily": "Tahoma, sans-serif"}}}%%
flowchart LR
  subgraph Era1["ยุค HTML Form / Native Form"]
    A["input + submit
ตรวจพื้นฐานใน Browser"] end subgraph Era2["ยุค Template Form / Simple Angular Form"] B["ngModel
เขียนง่ายใน Template"] end subgraph Era3["ยุค Reactive Form / Complex Form"] C["FormGroup/FormControl
ควบคุมใน Class"] D["Dynamic Form
สร้างฟอร์มตามข้อมูล"] end A --> B --> C --> D

แนวคิดสำคัญ

ตารางเปรียบเทียบฟอร์ม

หัวข้อ Template-driven Forms Reactive Forms
จุดควบคุมหลัก Template Component Class
ความง่าย ง่ายกว่า ต้องเขียนโค้ดมากกว่า
ฟอร์มซับซ้อน ไม่เหมาะมาก เหมาะมาก
Unit Test ยากกว่า ง่ายกว่า
Dynamic Form จำกัด ยืดหยุ่น
Module FormsModule ReactiveFormsModule

Mermaid Diagram: Forms Decision

%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#fabd2f", "primaryTextColor": "#282828", "primaryBorderColor": "#b57614", "lineColor": "#7c6f64", "secondaryColor": "#83a598", "tertiaryColor": "#b8bb26", "background": "#fbf1c7", "mainBkg": "#ebdbb2", "fontFamily": "Tahoma, sans-serif"}}}%%
flowchart TD
  A["ต้องสร้างฟอร์ม?
Need form?"] --> B{"ซับซ้อนหรือ Dynamic?
Complex or dynamic?"} B -->|ไม่ / No| C["Template-driven
ngModel"] B -->|ใช่ / Yes| D["Reactive Forms
FormGroup"] D --> E["Validators + Unit Test
ตรวจง่าย"] C --> F["FormsModule
ตั้งค่าง่าย"]

Code Example

// app.module.ts
// import module ให้ตรงกับชนิดฟอร์มที่ใช้
import { FormsModule, ReactiveFormsModule } from '@angular/forms';

@NgModule({
  imports: [
    FormsModule,
    ReactiveFormsModule
  ]
})
export class AppModule {}
<!-- template-driven example -->
<!-- ใช้ ngModel และ name เพื่อให้ Angular ติดตามค่า input -->
<form #loginForm="ngForm" (ngSubmit)="submitTemplate(loginForm.value)">
  <input name="email" ngModel required email>
  <button type="submit" [disabled]="loginForm.invalid">Login</button>
</form>
// reactive-form example
// สร้าง FormGroup ใน Component Class
import { Component } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';

@Component({
  selector: 'app-login-reactive',
  template: `
    <form [formGroup]="loginForm" (ngSubmit)="submitReactive()">
      <input formControlName="email">
      <p *ngIf="loginForm.controls.email.touched && loginForm.controls.email.invalid">
        กรุณากรอกอีเมลให้ถูกต้อง
      </p>
      <button type="submit" [disabled]="loginForm.invalid">Login</button>
    </form>
  `
})
export class LoginReactiveComponent {
  loginForm = new FormGroup({
    email: new FormControl('', [Validators.required, Validators.email])
  });

  submitReactive(): void {
    console.log(this.loginForm.value);
  }
}

// ตัวอย่างการใช้งาน:
// Reactive form เหมาะเมื่ออยากตรวจค่าหรือทดสอบ logic ใน TypeScript

กิจกรรมท้ายบท

  1. สร้างฟอร์ม login ด้วย Template-driven Forms
  2. สร้างฟอร์ม login แบบเดียวกันด้วย Reactive Forms
  3. เปรียบเทียบจำนวน logic ที่อยู่ใน Template กับ Component

กลับสัปดาห์ที่ 9