Cuộc Cách Mạng Của Angular 20: Khám Phá Input, Output và Model
Trong nhiều năm qua, các nhà phát triển Angular đã sử dụng các decorator @Input() và @Output() để giao tiếp giữa các component cha và con. Mặc dù rất mạnh mẽ, nhưng chúng thường tạo ra nhiều mã thừa và gây nhầm lẫn, đặc biệt là trong các ứng dụng lớn.
Với Angular 20, mọi thứ đã thay đổi một cách ngoạn mục. 🎉
Framework này giờ đây đã áp dụng các Signals và giới thiệu API model() cho một luồng trạng thái phản ứng sạch hơn.
🔴 Tại Sao Phải Chuyển Sang Signals?
- Quá nhiều nghi thức: các thuộc tính riêng biệt cho input/output.
- Dễ tạo ra luồng trạng thái lộn xộn trong các dự án lớn.
- Không phù hợp với các primitive phản ứng mới của Angular (Signals).
🟢 Angular 20: Inputs & Outputs Với Signals
Thay vì sử dụng decorators, Angular 20 cung cấp các hàm để định nghĩa các binding component:
input()→ thay thế cho @Input()output()→ thay thế cho @Output()model()→ kết hợp input + output thành một binding hai chiều duy nhất
📝 Ví Dụ Mã
🟢 Cách Cũ (Angular 19 với @Input và @Output)
typescript
// child.component.ts
import { Component, Input, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-child',
template: `
<p>{{ title }}</p>
<button (click)="notify()">Thông Báo Cha</button>
`
})
export class ChildComponent {
@Input() title!: string;
@Output() notifyParent = new EventEmitter<string>();
notify() {
this.notifyParent.emit('Xin chào từ Child!');
}
}
typescript
// parent.component.ts
@Component({
selector: 'app-parent',
template: `
<app-child
[title]="parentTitle"
(notifyParent)="onNotify($event)">
</app-child>
`
})
export class ParentComponent {
parentTitle = 'Cha nói chào!';
onNotify(msg: string) {
console.log(msg);
}
}
🔵 Cách Mới (Angular 20 với Signals)
typescript
// child.component.ts
import { Component, input, output } from '@angular/core';
@Component({
selector: 'app-child',
template: `
<p>{{ title() }}</p>
<button (click)="notify.emit('Xin chào từ Child!')">Thông Báo Cha</button>
`
})
export class ChildComponent {
title = input<string>();
notify = output<string>();
}
typescript
// parent.component.ts
@Component({
selector: 'app-parent',
template: `
<app-child
[title]="parentTitle"
(notify)="onNotify($event)">
</app-child>
`
})
export class ParentComponent {
parentTitle = 'Cha nói chào!';
onNotify(msg: string) {
console.log(msg);
}
}
💡 Hãy chú ý đến việc API mới này trông sạch sẽ và thân thiện với signals như thế nào!
🟣 Binding Hai Chiều Với model()
Điểm thay đổi thực sự là API model(), kết hợp input + output thành một signal duy nhất.
typescript
// child.component.ts
import { Component, model } from '@angular/core';
@Component({
selector: 'app-child',
template: `
<input [value]="title()" (input)="title.set($any($event.target).value)" />
<p>Bạn đã nhập: {{ title() }}</p>
`
})
export class ChildComponent {
title = model<string>(''); // binding hai chiều
}
typescript
// parent.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-parent',
template: `
<h2>Component Cha</h2>
<app-child [(title)]="parentTitle"></app-child>
<p>Giá trị Cha: {{ parentTitle }}</p>
`
})
export class ParentComponent {
parentTitle = 'Xin chào thế giới';
}
💡 API model() loại bỏ sự cần thiết của @Input() và @Output(), mang lại cho chúng ta binding hai chiều thực sự ngay từ đầu.
🌟 Tại Sao Điều Này Quan Trọng
- 🚀 Ít mã thừa, mã dễ đọc hơn
- 🔄 Binding hai chiều liền mạch với model()
- ⚡ Kiến trúc phản ứng đầu tiên, phù hợp với Angular Signals
- 🧩 Trải nghiệm lập trình viên tốt hơn và hiệu suất cao hơn
🏁 Kết Luận
Angular 20 đánh dấu một sự thay đổi lớn trong cách các component giao tiếp với nhau.
Với các hàm input(), output(), và đặc biệt là model(), chúng ta không cần nữa các decorators @Input() & @Output().
Đây không chỉ là một thay đổi API mà là một bước tiến hướng tới một hệ sinh thái Angular hoàn toàn phản ứng.
👉 Hãy theo dõi để biết thêm những điểm nổi bật sâu hơn về các tính năng mới của Angular 20!