Template Variable và ViewChild/ViewChildren trong Angular
- 21-12-2023
- Toanngo92
- 0 Comments
Mục lục
Các phần tử cha tương tác với phần tử con thông qua biến cục bộ
Để tương tác giữa một phần tử con và phần tử cha trong Angular, chúng ta có thể sử dụng biến cục bộ (Template variable) để truy cập các phương thức và thuộc tính của component con từ component cha.
Giả sử chúng ta có AppComponent chứa một phần template như sau:
<button (click)="doSomething()">Toggle</button>
<br />
<app-toggle #toggleComp></app-toggle>
Để gọi phương thức toggle()
của component ToggleComponent
từ AppComponent, chúng ta sử dụng Template variable #toggleComp
và kết hợp với sự kiện click của button:
<button (click)="toggleComp.toggle()">Toggle</button>
<br />
<app-toggle #toggleComp></app-toggle>
Cú pháp của Template variable là sử dụng #varName
và chúng ta có thể tạo nhiều biến trong template để tham chiếu đến các phần tử khác nhau.
Tương tự như khi sử dụng NgIf-Else, chúng ta cũng có thể sử dụng Template variable để tham chiếu đến các ng-template
và truyền chúng vào directive như NgIf
hoặc NgIfElse
:
<div *ngIf="user.age >= 13; else noPG13">Bạn có thể xem nội dung PG-13</div>
<ng-template #noPG13>
<div>Bạn không thể xem nội dung PG-13</div>
</ng-template>
Điều này cho phép chúng ta tận dụng biến cục bộ để truy cập và tương tác giữa các phần tử trong cùng một template, giúp quản lý và điều khiển các component một cách linh hoạt.
Template variable sẽ là instance của class nào?
Một Template variable trong Angular có thể là một instance của một HTMLElement hoặc một Component. Khi không sử dụng cú pháp #varName="exportAsOfDirectiveOrComponent"
, Template variable sẽ cố gắng lấy về một đối tượng tương ứng. Với HTMLElement, đó sẽ là HTMLElement; và với Component, đó sẽ là một instance của Component đó.
Ví dụ, trong trường hợp của FormsModule và ngModel, chúng ta sử dụng cú pháp:
<form #nameForm="ngForm">
<input
type="text"
class="form-control"
required
[(ngModel)]="model.name"
name="name"
#name="ngModel"
/>
<button>Submit</button>
</form>
Ở đây, chúng ta tạo ra hai Template variable:
nameForm
: mong muốn lấy instance của directive cóexportAs
làngForm
.name
: mong muốn lấy instance của directive cóexportAs
làngModel
.
Sử dụng #varName="exportAsOfDirectiveOrComponent"
giúp chúng ta yêu cầu lấy chính xác instance của directive hoặc component đó. Nếu không yêu cầu cụ thể, các Template variable sẽ trả về HTMLElement thông thường.
Qua cách sử dụng Template variable và cú pháp exportAs
, chúng ta có khả năng lấy đối tượng mong muốn từ các directive và components trong Angular templates để thực hiện các thao tác tương ứng.
Parent class with ViewChild
Để truy cập Template variable trong class của một component, chúng ta có thể sử dụng @ViewChild
. Điều này cho phép chúng ta truy cập và tương tác với các phần tử hoặc component từ logic của component, không chỉ từ template.
Ví dụ, nếu chúng ta muốn gọi đến Template variable trong class của một component, chúng ta có thể sử dụng @ViewChild
như sau:
<button (click)="toggleInside()">Toggle inside class</button>
<br />
<br />
<app-toggle #toggleComp></app-toggle>
export class AppComponent {
@ViewChild("toggleComp") toggleComp: ToggleComponent;
toggleInside() {
this.toggleComp.toggle();
}
}
Nếu chúng ta sử dụng @ViewChild
cho một HTMLElement, chúng ta sẽ nhận được một ElementRef
thay vì một HTMLElement
như khi sử dụng trong template.
<div #chartContainer></div>
export class AppComponent {
@ViewChild("chartContainer") container: ElementRef<HTMLDivElement>;
}
@ViewChild
cũng cho phép chúng ta truyền vào các cấu hình tùy chỉnh, như read
hoặc static
, để định rõ loại instance cần lấy và cách thức truy cập.
export class NameFormComponent implements OnInit {
model = {
name: "Tiep Phan",
};
@ViewChild("nameForm", {
read: ElementRef,
static: true,
})
form: ElementRef<HTMLFormElement>;
ngOnInit() {
console.log(this.form);
}
}
Qua cách sử dụng @ViewChild
với cấu hình tùy chỉnh như read
và static
, chúng ta có thể xác định loại instance cần lấy và quyết định thời điểm tiến trình của nó sẽ được chạy, giúp tương tác và điều khiển các phần tử và component từ logic của component một cách linh hoạt và hiệu quả.
Parent class with ViewChildren
Để truy vấn một danh sách các phần tử trong Angular, chúng ta có thể sử dụng ViewChildren
. ViewChildren
trả về một QueryList
trước khi hàm ngAfterViewInit
được gọi. QueryList
này chứa các thuộc tính và phương thức cho phép chúng ta lắng nghe các sự kiện (Observable).
Ví dụ, nếu chúng ta muốn truy vấn một danh sách các ToggleComponent
, chúng ta có thể sử dụng ViewChildren
như sau:
<app-toggle></app-toggle>
<br />
<app-toggle></app-toggle>
import { ViewChildren, QueryList, AfterViewInit } from '@angular/core';
import { ToggleComponent } from './toggle.component';
export class AppComponent implements AfterViewInit {
@ViewChildren(ToggleComponent) toggleList: QueryList<ToggleComponent>;
ngAfterViewInit() {
console.log(this.toggleList);
}
}
Trong đoạn mã trên, chúng ta đã sử dụng @ViewChildren
để truy vấn danh sách các ToggleComponent
trong template của AppComponent. Khi hàm ngAfterViewInit
được gọi, this.toggleList
sẽ chứa danh sách các ToggleComponent
tương ứng và chúng ta có thể thực hiện các thao tác tiếp theo trên QueryList
này.