Bài viết này, mình sẽ tổng hợp có những cách nào để chia sẻ dữ liệu giữa các Component trong Angular, Hiện tại có những cách sau đây:
- Sử dụng @Input và @Output giữa thành phần cha và con.
- Sử dụng ViewChild, ViewContent để truy xuất dữ liệu ban đầu của thành phần con.
- Sử dụng BehaviorSubject trong RxJS.
Sử dụng @Input và @Output giữa thành phần cha và con
Ở component con muốn nhận dữ liệu từ component cha, thì ở component con sử dụng decorator @Input, cách sử dụng như sau:
import { Component, Input } from '@angular/core' @Component({ selector: 'child-component', template: ` <h3>Hello, {{hello}}</h3> ` }) export class ChildComponent { @Input() hello: string; };
Khi đó, ở component cha ta có thể truyền dữ liệu cho con theo cách bình thường:
import { Component } from '@angular/core'; @Component({ selector: 'parent-component', template: ` <h2>Parent component</h2> <child-component hello="truongluu"></child-component> ` }) export class ParentComponent { }
Lưu ý: khi sử dụng decorator @Input, ta có thêm lựa con là thiết lập tham số đầu vào, nó là alias của thuộc tính truyền vào và biến bên trong component con. Cách sử dụng như sau
@Input('message') hello: string;
và lúc này dữ liệu được truyền vào từ cha sẽ viết lại như sau:
@Component({ selector: 'parent-component', template: ` <h2>Parent component</h2> <child-component message="truongluu"></child-component> ` })
Ngược tại, từ component con muốn truyền dữ liệu cho cha, thì ta có thêm khái niệm EventEmitter (Người phát sự kiện), là khi ở con có một sự kiện gì đó làm thay đổi dữ liệu, mà ở cha muốn nhận dữ liệu đó thì con sẽ đẩy dữ liệu này cho cha thông qua sử dụng @Output và EventEmitter ở con (hay còn gọi là tuỳ chỉnh sự kiện). Cách sử dụng như sau:
import { Component, Input, Output, EventEmitter } from '@angular/core' @Component({ selector: 'child-component', template: ` <h3>Child component, Hello: {{hello}}</h3> <button (click)="changeMessage()">Change message to "mono"</button> ` }) export class ChildComponent { @Input() hello: string; @Output() messageChanged: EventEmitter<string> = new EventEmitter(); changeMessage() { this.messageChanged.emit('mono'); } };
Sử dụng decorator @Output, để khai báo đầu ra cho component con, với cách khai báo
@Output() messageChanged: EventEmitter<string> = new EventEmitter();
thì ở component cha, khi gọi component con, sẽ theo cấu trúc:
import { Component } from '@angular/core'; @Component({ selector: 'parent-component', template: ` <h2>Parent component</h2> {{message}} <child-component hello="truongluu" (messageChanged)="changeMessage($event)"></child-component> ` }) export class ParentComponent { message: string = ''; changeMessage($event) { this.message = $event; } }
Với,
(messageChanged): là tên @Output đã khai báo trong component con, và trong component cha sẽ khai báo 1 hàm để nhận dữ liệu từ con phát ra (this.messageChanged.emit(‘mono’), cụ thể là phát ra chuỗi “mono” khi click và button ở con.
và dữ liệu được phát ra từ con cho cha là dữ liệu dạng chuỗi (EventEmitter<string>). Trường hợp, muốn phát ra dữ liệu gì thì bạn định nghĩa trong EventEmitter<data-type>.
Cũng giống như sài @Input, thì @Output cũng cho thiết lập alias tham chiếu vào biến,
Ví dụ: ở component con ta khai báo lại
export class ChildComponent { @Input() hello: string; @Output('changed') messageChanged: EventEmitter<string> = new EventEmitter(); changeMessage() { this.messageChanged.emit('mono'); } };
Lúc này, ở component cha ta sử dụng alias (changed) là output để phát ra dữ liệu cho cha