Nếu bạn đang sử dụng các thành phần được tạo động trong Angular, có thể bạn sẽ gặp khó khăn khi truyền thông tin giữa các thành phần cha và con khi cần. Bạn cần cung cấp thông tin trong thành phần cha, sau đó đưa thông tin đó vào thành phần con. Mặc dù điều này không hẳn là khó thực hiện nhưng nó dẫn đến rất nhiều mã soạn sẵn bổ sung.
Sẽ tốt hơn rất nhiều nếu chúng ta có thể sử dụng trang trí @Input
như chúng ta đã quen. Cũng đoán những gì? Angular hỗ trợ thực hiện chính xác điều này kể từ phiên bản mười sáu. Trong bài đăng này, tôi sẽ chỉ cho bạn cách. Được rồi, bắt đầu thôi.
Trước tiên, hãy xem cách chúng ta sử dụng để truyền dữ liệu đến các thành phần được tạo động từ thành phần gốc. Ở đây, trong ví dụ này, trong mẫu thành phần, chúng ta có *ngComponentOutlet
và chúng ta chuyển nó cho thành phần trình phát của mình.
Trong trường hợp này, chúng tôi cũng chuyển một trình tiêm con tùy chỉnh và đây là cách chúng tôi chèn dữ liệu cho thành phần con trước đó.
@Component({ selector: 'app-root', template: ` <ng-container *ngComponentOutlet="playerComponent; injector: childInjector"></ng-container> ` }) export class App { protected playerComponent = PlayerComponent; }
Và để tạo bộ tiêm con này, chúng ta cần tạo một thuộc tính để có thể đặt và sử dụng nó trong mẫu.
export class App { protected childInjector?: Injector; ... }
Sau đó, chúng ta cần chèn Injector từ lõi góc bên trong hàm tạo.
export class App { ... constructor(private injector: Injector) { } }
Sau đó, chúng tôi cần thiết lập trình tiêm con bằng phương thức tạo và mảng của nhà cung cấp để cung cấp mã thông báo trình phát của chúng tôi cho trẻ.
export class App { ... constructor(private injector: Injector) { this.childInjector = Injector.create({ providers: [ { provide: PlayerToken, useValue: this.player } ], parent: this.injector }); } }
Và cuối cùng, trong thành phần con, thành phần trình phát của chúng ta, chúng ta cần đặt thuộc tính trình phát của mình bằng phương thức tiêm từ lõi góc.
export class PlayerComponent { protected player?: Player = inject(PlayerToken); }
Vì vậy, tất cả những điều này chỉ nhằm chuyển một đối tượng trình phát đơn giản sang một thành phần động. Ý tôi là, nếu đây không phải là thành phần động thì chúng ta chỉ cần đặt thành phần này là @Input
và chỉ liên kết đối tượng dữ liệu người chơi với @Input
trong phần tử mẹ. Nhưng đây là một thành phần được tạo động nên chúng ta không thể làm được điều này phải không?
Chà, kể từ Angular 16, chúng ta thực sự có thể sử dụng @Input
s thay thế và nó đơn giản hơn nhiều so với những gì chúng ta đã thấy cho đến nay.
*ngComponentOutlet
Thay vào đó, chúng tôi bắt đầu bằng cách thay đổi thuộc tính trình phát này thành @Input
. Và nó chỉ đơn giản được gõ vào giao diện trình phát của chúng tôi.
export class PlayerComponent { @Input() player?: Player; }
Bây giờ, chúng tôi có thể xóa phương thức tiêm và nhập mã thông báo người chơi vì chúng không còn cần thiết nữa. Sau đó, quay lại phần cha mẹ của chúng ta, trong mẫu, chúng ta có thể loại bỏ bộ tiêm và thay vào đó, thay thế nó bằng một đối tượng đầu vào. Chúng ta có thể truyền đối tượng này vào bất kỳ số lượng đầu vào nào. Vì vậy, nếu có năm đầu vào, chúng tôi sẽ chỉ bao gồm tên của chúng và sau đó chuyển cho mỗi đầu vào bất kỳ dữ liệu nào chúng tôi cần.
Nhưng trong trường hợp này, chúng ta chỉ có một đầu vào trên thành phần con, trình phát, vì vậy đó là tất cả những gì chúng ta cần để truyền nó.
@Component({ selector: 'app-root', template: ` <ng-container *ngComponentOutlet="playerComponent; inputs: { player }"></ng-container> ` })
Bây giờ, chúng ta có thể loại bỏ bộ tiêm con. Điều này có nghĩa là chúng ta cũng có thể loại bỏ hoàn toàn hàm tạo. Và cuối cùng, chúng ta có thể loại bỏ Injector khỏi lõi góc và nhập mã thông báo người chơi vì chúng ta không còn sử dụng chúng nữa.
export class App { protected player: Player = { name: 'LeBron James', games: 1421, points: 38652, fieldGoalPercentage: 0.505, threePointPercentage: 0.345, imageName: 'lebron-james' }; protected playerComponent = PlayerComponent; }
Và thế là xong. Chúng ta có thể thấy mọi thứ vẫn hoạt động như trước đây. Vì vậy, việc thực hiện dễ dàng hơn một chút và ít mã hơn, điều này luôn tuyệt vời.
Tuy nhiên, một điều đáng tiếc là trong khi @Input
s được hỗ trợ, thì @Output
lại không. Thật là một điều ngớ ngẩn, nhưng nó là như vậy. Hy vọng rằng họ sẽ bổ sung thêm hỗ trợ trong tương lai vì điều này cũng sẽ rất tiện dụng, nhưng chúng ta sẽ phải chờ xem.
Hãy xem mã demo và ví dụ về các kỹ thuật này trong ví dụ về Stackblitz bên dưới. Nếu bạn có bất kỳ câu hỏi hoặc suy nghĩ nào, đừng ngần ngại để lại nhận xét.