Dynamic Component trong Angular
- 15-01-2024
- Toanngo92
- 0 Comments
Mục lục
Mở đầu
Qua những bài trước, bạn đã hiểu cách tạo các thành phần con và cha cũng như cách chúng tương tác. Bây giờ, hãy xem xét một tình huống cụ thể: Component A là cha của Component B, có dạng như sau:
Trong nhiều tình huống, chúng ta mong muốn có khả năng thay đổi thành phần hiển thị trong quá trình chạy ứng dụng, không chỉ giới hạn cứng một Component B nhất định. Có thể là Component B hoặc Component C tùy thuộc vào logic của ứng dụng. Hoặc trong một tình huống khác, chúng ta muốn người dùng thực hiện một hành động nào đó trong Component A trước khi hiển thị Component B.
Trong trường hợp thông thường, Component B thường được xác định cứng trong template là con của A.
Vậy làm thế nào để load một Component khác vào trong Component A trong quá trình chạy ứng dụng? Điều này sẽ được giải quyết thông qua Dynamic Component, chủ đề mà chúng ta sẽ khám phá trong bài viết hôm nay.
Coding Practice
Bài viết này hướng dẫn về việc sử dụng Dynamic Components trong Angular để load các thành phần động trong quá trình runtime. Dưới đây là một số bước chính:
Bước 1: Khởi tạo Dự án
ng new dynamic-component-demo
Bước 2: Tạo Các Components
ng g c example-container
ng g c dynamic-content-one
ng g c dynamic-content-two
Thêm app-example-container
vào template của app.component.html
.
Bước 3: Code Container Components
// example-container.component.ts
import { Component, OnInit, ViewChild, ViewContainerRef, ComponentFactoryResolver } from "@angular/core";
import { DynamicContentOneComponent } from "../dynamic-content-one/dynamic-content-one.component";
import { DynamicContentTwoComponent } from "../dynamic-content-two/dynamic-content-two.component";
@Component({
selector: "app-example-container",
templateUrl: "./example-container.component.html",
styleUrls: ["./example-container.component.scss"],
})
export class ExampleContainerComponent implements OnInit {
@ViewChild("dynamicComponent", { read: ViewContainerRef, static: true })
containerRef: ViewContainerRef;
constructor(private cfr: ComponentFactoryResolver) {}
ngOnInit() {}
addDynamicCompOne() {
const componentFactory = this.cfr.resolveComponentFactory(DynamicContentOneComponent);
const componentRef = this.containerRef.createComponent(componentFactory);
}
addDynamicCompTwo() {
const componentFactory = this.cfr.resolveComponentFactory(DynamicContentTwoComponent);
const componentRef = this.containerRef.createComponent(componentFactory);
}
}
Bước 4: Thêm Các Dynamic Components Vào entryComponents
// app.module.ts
@NgModule({
declarations: [
AppComponent,
ExampleContainerComponent,
DynamicContentOneComponent,
DynamicContentTwoComponent,
],
imports: [BrowserModule],
providers: [],
bootstrap: [AppComponent],
entryComponents: [DynamicContentOneComponent, DynamicContentTwoComponent],
})
export class AppModule {}
Bước 5: Clear Các Dynamic Components
Thêm nút “Clear” để xóa các component đã load.
// example-container.component.ts
clearDynamicComp() {
this.containerRef.clear();
}
Bước 6: Tương Tác Với Các Dynamic Components
Tương tác giữa container và dynamic components tương tự như tương tác giữa component cha và con.
// dynamic-content-one.component.ts
@Input()
data: string;
<!-- dynamic-content-one.component.html -->
<h1>DYNAMIC CONTENT 1</h1>
<p>++++++{{data}}+++++++++</p>
// example-container.component.ts
addDynamicCompOne() {
const componentFactory = this.cfr.resolveComponentFactory(DynamicContentOneComponent);
const componentRef = this.containerRef.createComponent(componentFactory);
componentRef.instance.data = "INPUT DATA 1";
}
Bước 7: Cập Nhật Với Angular Ivy Lazy Load
Cập nhật code để sử dụng tính năng lazy load với Angular Ivy.
// example-container.component.ts
async addDynamicCompOne() {
const { DynamicContentOneComponent } = await import('../dynamic-content-one/dynamic-content-one.component');
const componentFactory = this.cfr.resolveComponentFactory(DynamicContentOneComponent);
const componentRef = this.containerRef.createComponent(componentFactory);
componentRef.instance.data = "INPUT DATA 1";
}
Đây là một hướng dẫn đơn giản về việc sử dụng Dynamic Components trong Angular để load và quản lý các thành phần động trong ứng dụng.
Concepts
ViewContainerRef
ViewContainerRef là một loại “hộp” trong Angular, giúp chúng ta quản lý việc tạo và quản lý các view trong ứng dụng. Nó giống như một “khu vực” từ nơi chúng ta có thể tạo ra các thành phần (components) và views (các hiển thị) trong ứng dụng.
Khi chúng ta tạo một Host View (một loại view tương ứng với component), hoặc một Embedded View (được tạo từ một TemplateRef), ViewContainerRef chính là nơi chúng ta có thể “đặt” chúng. Nó hỗ trợ chúng ta trong việc quản lý vị trí và vòng đời của các view này.
ViewContainerRef cũng có khả năng chứa các container khác bên trong nó, giống như cách ng-container hoạt động. Điều này tạo nên một cấu trúc cây, giúp quản lý và nhóm hóa các view và components trong ứng dụng.
Nói một cách đơn giản, bạn có thể xem ViewContainerRef như một “đối tượng chứa” giúp bạn thêm và quản lý các thành phần và hiển thị chúng trong ứng dụng của mình.
ComponentFactory
ComponentFactory là một “nhà máy” cho việc tạo ra các components một cách động trong Angular. Nó chủ yếu được sử dụng để tạo ra một instance của một component dựa trên thông tin từ ComponentFactoryResolver.
Khi chúng ta cần tạo một component trong quá trình chạy ứng dụng, chúng ta sử dụng ComponentFactory để nhận thông tin về cách component đó được xây dựng và cách chúng ta có thể tạo ra một phiên bản của nó.
Nói một cách đơn giản, ComponentFactory có thể được coi là “mô-đun sản xuất” giúp chúng ta sản xuất các components tại thời điểm chạy của ứng dụng Angular.
ComponentFactoryResolver
ComponentFactoryResolver
là một công cụ trong Angular giúp chúng ta xác định cách tạo một ComponentFactory
từ một loại component cụ thể. Nó nhận các thông tin về component và sau đó chúng ta có thể sử dụng ComponentFactory
để tạo ra các phiên bản của component đó.
Nói một cách đơn giản, ComponentFactoryResolver
là người giúp chúng ta “giải quyết bí ẩn” về cách tạo một ComponentFactory
từ một loại component. Khi chúng ta cần tạo các phiên bản của một component trong quá trình chạy ứng dụng, chúng ta sẽ sử dụng ComponentFactoryResolver
để lấy thông tin cần thiết và sau đó sử dụng ComponentFactory
để tạo các phiên bản thực tế của component đó.
Khi đã có ComponentFactory
, chúng ta có thể sử dụng ViewContainerRef
để chèn component vào vị trí cụ thể trong ứng dụng của chúng ta, chẳng hạn như trong một div
hoặc bất kỳ nơi nào chúng ta muốn.