Angular의 동적 컴포넌트 생성 기능인 createComponent를 활용하여, 마우스를 올렸을 때 나타나는 동적 툴팁(Tooltip)을 만들어 봅시다.
툴팁을 표시할 div 요소들을 만들고, 우리가 만들 tooltip 디렉티브를 적용합니다.
// src/app/container.component.ts
import { Component } from '@angular/core';
import { TooltipDirective } from './tooltip.directive';
@Component({
selector: 'app-container',
standalone: true,
imports: [TooltipDirective], // 사용할 디렉티브를 import
template: `
<h2>Hover over these elements</h2>
<div class="box" [tooltip]="'A'">Show Tooltip A</div>
<div class="box" [tooltip]="'B'">Show Tooltip B</div>
`,
styles: `
.box {
border: 1px solid #ccc;
padding: 20px;
margin: 20px;
cursor: pointer;
width: 200px;
text-align: center;
}
`
})
export class ContainerComponent {}
화면에 표시될 두 개의 간단한 툴팁 컴포넌트를 작성합니다.
// src/app/a-tooltip.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'a-tooltip',
standalone: true,
template: `<div class="tooltip">Tooltip A: Hello World</div>`,
styles: `.tooltip { background-color: lightblue; padding: 10px; border-radius: 5px; }`
})
export class ATooltipComponent {}
// src/app/b-tooltip.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'b-tooltip',
standalone: true,
template: `<div class="tooltip">Tooltip B: Goodbye</div>`,
styles: `.tooltip { background-color: lightcoral; color: white; padding: 10px; border-radius: 5px; }`
})
export class BTooltipComponent {}
이 예제의 핵심 로직입니다. 디렉티브에서 이벤트를 감지하고, 입력 값('A' 또는 'B')에 따라 적절한 툴팁 컴포넌트를 동적으로 생성하고 제거합니다.
// src/app/tooltip.directive.ts
import {
Directive,
Input,
HostListener,
ComponentRef,
ViewContainerRef,
inject,
Type
} from '@angular/core';
import { ATooltipComponent } from './a-tooltip.component';
import { BTooltipComponent } from './b-tooltip.component';
@Directive({
selector: '[tooltip]',
standalone: true,
})
export class TooltipDirective {
@Input('tooltip') type: 'A' | 'B' | string = '';
private componentRef?: ComponentRef<any>;
// inject 함수로 ViewContainerRef를 주입받습니다.
private viewContainerRef = inject(ViewContainerRef);
@HostListener('mouseenter')
onMouseEnter(): void {
if (this.componentRef) return; // 이미 툴팁이 있으면 생성하지 않음
const componentToCreate = this.getComponentType(this.type);
if (!componentToCreate) return;
// ComponentFactoryResolver 없이 컴포넌트 클래스를 직접 전달
this.componentRef = this.viewContainerRef.createComponent(componentToCreate);
}
@HostListener('mouseleave')
onMouseLeave(): void {
if (this.componentRef) {
this.componentRef.destroy();
this.componentRef = undefined;
}
}
private getComponentType(type: string): Type<any> | null {
switch (type) {
case 'A':
return ATooltipComponent;
case 'B':
return BTooltipComponent;
default:
return null;
}
}
}
NgModule을 사용하던 과거와 달리, Standalone 환경에서는 각 컴포넌트와 디렉티브가 필요한 의존성을 imports 배열에 직접 명시해야 합니다.
이제 예제를 실행하고 각 div 요소 위로 마우스를 가져가면, 해당 타입에 맞는 툴팁이 동적으로 생성되고 사라지는 것을 확인할 수 있습니다.