Angular Signal-based Inputs และ Outputs: วิธีใหม่ที่ดีกว่า @Input @Output

#angular12 เม.ย. 2569

Signal-based Inputs (Angular 17.1+)

Angular 17.1 แนะนำ input() function ที่ return Signal แทนการใช้ @Input() decorator ทำให้ reactive มากขึ้น

input() — Signal Input

import { Component, input, computed } from '@angular/core';

@Component({
  selector: 'app-user-card',
  template: `
    <h2>{{ user().name }}</h2>
    <p>{{ fullInfo() }}</p>
  `
})
export class UserCardComponent {
  // Required input
  user = input.required<User>();

  // Optional input with default
  showEmail = input(false);

  // Computed จาก input signal
  fullInfo = computed(() => {
    const u = this.user();
    return `${u.name} (${u.email})`;
  });
}

เปรียบเทียบกับ @Input()

// เดิม - ไม่ reactive
@Input() user!: User;

// ใหม่ - reactive signal
user = input.required<User>();

// ใช้ค่า
const name = this.user().name; // เรียกเหมือน signal

output() — Signal Output

import { Component, output } from '@angular/core';

@Component({
  selector: 'app-counter',
  template: `<button (click)="increment()">+1</button>`
})
export class CounterComponent {
  countChange = output<number>();
  private count = 0;

  increment() {
    this.count++;
    this.countChange.emit(this.count);
  }
}

model() — Two-way Binding Signal

import { Component, model } from '@angular/core';

@Component({
  selector: 'app-input',
  template: `
    <input [value]="value()" (input)="value.set($event.target.value)" />
  `
})
export class InputComponent {
  value = model('');
}

// Parent
// <app-input [(value)]="myValue" />

ข้อดี

  • Type-safe กว่า @Input()
  • Reactive ใช้กับ computed() ได้ทันที
  • Required inputs ตรวจสอบ compile time
  • ไม่ต้องใช้ ngOnChanges เพื่อ react ต่อการเปลี่ยนแปลง

สรุป

Signal-based inputs/outputs เป็นอนาคตของ Angular component API ควรเริ่มใช้ในโปรเจ็คใหม่ครับ