หัวข้อ 5: Decorator เบื้องต้น ใช้ใน Angular

คำจำกัดความ

Decorator คือฟังก์ชันพิเศษที่ใช้ annotate class, method หรือ property เพื่อเพิ่ม metadata หรือปรับพฤติกรรม ใน Angular ใช้ decorator จำนวนมาก เช่น @Component, @Injectable, @Input

%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#458588", "primaryTextColor": "#fbf1c7", "primaryBorderColor": "#fabd2f", "lineColor": "#a89984", "secondaryColor": "#b8bb26", "tertiaryColor": "#d3869b", "background": "#282828", "mainBkg": "#3c3836", "textColor": "#ebdbb2"}}}%%
flowchart LR
  A["Decorator
ฟังก์ชัน Annotate"] --> B["Class
@Component"] A --> C["Method
@HostListener"] A --> D["Property
@Input @Output"] B --> E["Metadata
ข้อมูลกำกับ Angular"]

Decorator ใน Angular

Decorator ประเภท ใช้ทำอะไร
@Component Class ประกาศ component
@NgModule Class ประกาศ module
@Injectable Class ประกาศ service ที่ DI ได้
@Input() Property รับข้อมูลจาก parent
@Output() Property ส่ง event ไป parent
@HostListener Method ฟัง event จาก host/window
@ViewChild Property อ้างอิง child element/component

เปิดใช้ Decorator ใน tsconfig

{
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  }
}

ตัวอย่างแนวคิด Angular Decorator

// ตัวอย่างโครงสร้าง ไม่จำเป็นต้องรันนอก Angular
@Component({
  selector: "app-course-card",
  template: "<h2>{{ title }}</h2>"
})
export class CourseCardComponent {
  @Input() title = "";
}

Custom Class Decorator อย่างง่าย

function LogClass(constructor: Function) {
  // แสดงชื่อ class ที่ถูก decorate
  console.log(`สร้าง class: ${constructor.name}`);
}

@LogClass
class CourseService {
  getTitle(): string {
    return "Web Programming";
  }
}

// ตัวอย่างการใช้งาน
const service = new CourseService();
console.log(service.getTitle());

Method Decorator อย่างง่าย

function LogMethod(
  target: object,
  propertyKey: string,
  descriptor: PropertyDescriptor
) {
  const original = descriptor.value;

  descriptor.value = function (...args: unknown[]) {
    // log ก่อนเรียก method จริง
    console.log(`เรียก method: ${propertyKey}`);
    return original.apply(this, args);
  };
}

class Calculator {
  @LogMethod
  add(a: number, b: number): number {
    return a + b;
  }
}

const calculator = new Calculator();
console.log(calculator.add(2, 3));

สมการจำนวน Metadata

M = C + P + F

โดยที่ M คือจำนวน metadata รวม, C คือ class decorators, P คือ property decorators, และ F คือ method decorators

แบบทดสอบหลังเรียน

  1. Decorator คืออะไร
  2. @Component ใช้ทำอะไร
  3. @Input() และ @Output() ต่างกันอย่างไร
  4. ต้องตั้งค่าอะไรใน tsconfig.json เพื่อใช้ decorator
  5. Custom decorator มีประโยชน์อย่างไร

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