본문 바로가기

개발 공부/Angular

ng-template / Angular (2)

동적 콘텐츠 렌더링: 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