동적 콘텐츠 렌더링: ViewContainerRef와 TemplateRef
ng-template의 강력한 점 중 하나는 Angular가 제공하는 ViewContainerRef와 TemplateRef를 사용해 동적으로 템플릿을 렌더링할 수 있다는 것입니다.
HTML
<button (click)="loadTemplate()">템플릿 로드</button>
<ng-template #dynamicTemplate>
<p>이 템플릿은 동적으로 렌더링되었습니다!</p>
</ng-template>
TypeScript
import { Component, TemplateRef, ViewChild, ViewContainerRef } from '@angular/core';
@Component({
selector: 'app-dynamic-rendering',
templateUrl: './dynamic-rendering.component.html',
})
export class DynamicRenderingComponent {
@ViewChild('dynamicTemplate') template!: TemplateRef<any>;
constructor(private viewContainerRef: ViewContainerRef) {}
loadTemplate() {
this.viewContainerRef.createEmbeddedView(this.template);
}
}
- @ViewChild 데코레이터로 템플릿 참조를 가져옵니다.
- ViewContainerRef의 createEmbeddedView 메서드를 호출해 템플릿을 동적으로 렌더링합니다.
- 버튼 클릭 시 템플릿이 DOM에 삽입됩니다.
템플릿 인수 전달: ngTemplateOutlet과 context
ng-template을 사용할 때, 템플릿에 데이터를 동적으로 전달하는 것이 가능합니다.
이를 위해 ngTemplateOutlet과 context를 사용합니다.
HTML
<ng-template #greetingTemplate let-name="name">
<p>안녕하세요, {{ name }}!</p>
</ng-template>
<ng-container *ngTemplateOutlet="greetingTemplate; context: { name: 'Angular' }"></ng-container>
TypeScript
import { Component } from '@angular/core';
@Component({
selector: 'app-template-context',
templateUrl: './template-context.component.html',
})
export class TemplateContextComponent {}
- ngTemplateOutlet은 템플릿을 렌더링하며, context를 통해 데이터를 전달합니다.
- 템플릿 내부에서 let-변수명 구문으로 데이터를 참조합니다.
- 위 코드에서는 name이라는 데이터를 템플릿에 전달해 동적으로 값을 출력합니다.
재사용 가능한 UI 컴포넌트 설계
ng-template을 활용하면 특정 UI 로직을 재사용 가능하게 설계할 수 있습니다.
예를 들어, 데이터 테이블의 각 행을 ng-template으로 정의해 원하는 모양대로 커스터마이즈할 수 있습니다.
HTML 코드 (부모 컴포넌트)
<app-data-table [data]="users" [rowTemplate]="userRowTemplate"></app-data-table>
<ng-template #userRowTemplate let-user>
<tr>
<td>{{ user.id }}</td>
<td>{{ user.name }}</td>
<td>{{ user.email }}</td>
</tr>
</ng-template>
TypeScript 코드 (부모 컴포넌트)
import { Component } from '@angular/core';
@Component({
selector: 'app-parent',
templateUrl: './parent.component.html',
})
export class ParentComponent {
users = [
{ id: 1, name: 'John Doe', email: 'john.doe@example.com' },
{ id: 2, name: 'Jane Smith', email: 'jane.smith@example.com' },
];
}
HTML 코드 (데이터 테이블 컴포넌트)
<table>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<ng-container *ngFor="let item of data">
<ng-container *ngTemplateOutlet="rowTemplate; context: { $implicit: item }"></ng-container>
</ng-container>
</tbody>
</table>
TypeScript 코드 (데이터 테이블 컴포넌트)
import { Component, Input, TemplateRef } from '@angular/core';
@Component({
selector: 'app-data-table',
templateUrl: './data-table.component.html',
})
export class DataTableComponent {
@Input() data: any[] = [];
@Input() rowTemplate!: TemplateRef<any>;
}
- ngTemplateOutlet으로 부모 컴포넌트에서 정의한 템플릿을 자식 컴포넌트에서 렌더링합니다.
- $implicit 키워드를 사용해 데이터를 템플릿으로 전달합니다.
- 부모 컴포넌트는 데이터를 제공하고, 자식 컴포넌트는 템플릿과 데이터를 결합해 화면에 렌더링합니다.
ng-template의 장단점
장점
- 유연성: 다양한 상황에서 재사용 가능
- 동적 콘텐츠: 런타임에 콘텐츠를 동적으로 추가 가능
- UI 커스터마이징: 복잡한 UI 로직을 간결하게 구현
단점
- 복잡성 증가: 남용하면 코드 가독성이 떨어질 수 있음
- 런타임 의존성: 런타임에 템플릿이 결정되므로 디버깅이 어려울 수 있음
'개발 공부 > Angular' 카테고리의 다른 글
| Angular Routing Resolver (1) | 2024.12.11 |
|---|---|
| ng-template / ng-container 차이 (1) | 2024.12.10 |
| ng-template / Angular (1) (0) | 2024.12.05 |
| ng-container / Angular (2) (0) | 2024.12.02 |
| ng-container / Angular (1) (1) | 2024.12.01 |