Angular에서 NgTemplateOutlet을 사용하여 재사용 가능한 구성 요소를 만드는 방법
소개
단일 책임 원칙은 애플리케이션의 일부가 하나의 목적을 가져야 한다는 생각입니다. 이 원칙을 따르면 Angular 앱을 더 쉽게 테스트하고 개발할 수 있습니다.
Angular에서 특정 구성 요소를 만드는 대신 NgTemplateOutlet
을 사용하면 구성 요소 자체를 수정하지 않고도 다양한 사용 사례에 맞게 구성 요소를 쉽게 수정할 수 있습니다!
이 문서에서는 기존 구성 요소를 가져와 NgTemplateOutlet
을 사용하도록 다시 작성합니다.
전제 조건
이 자습서를 완료하려면 다음이 필요합니다.
- Node.js를 로컬에 설치했습니다. Node.js를 설치하고 로컬 개발 환경을 만드는 방법에 따라 수행할 수 있습니다.
- Angular 프로젝트 설정에 어느 정도 익숙합니다.
이 튜토리얼은 Node v16.6.2, npm
v7.20.6 및 @angular/core
v12.2.0에서 검증되었습니다.
1단계 – CardOrListViewComponent 구성
모드
카드 또는 목록
형식으로 항목
을 표시하는 CardOrListViewComponent
를 고려하십시오. >.
card-or-list-view.component.ts
파일로 구성됩니다.
import {
Component,
Input
} from '@angular/core';
@Component({
selector: 'card-or-list-view',
templateUrl: './card-or-list-view.component.html'
})
export class CardOrListViewComponent {
@Input() items: {
header: string,
content: string
}[] = [];
@Input() mode: string = 'card';
}
그리고 card-or-list-view.component.html
템플릿:
<ng-container [ngSwitch]="mode">
<ng-container *ngSwitchCase="'card'">
<div *ngFor="let item of items">
<h1>{{item.header}}</h1>
<p>{{item.content}}</p>
</div>
</ng-container>
<ul *ngSwitchCase="'list'">
<li *ngFor="let item of items">
{{item.header}}: {{item.content}}
</li>
</ul>
</ng-container>
다음은 이 구성 요소의 사용 예입니다.
import { Component } from '@angular/core';
@Component({
template: `
<card-or-list-view
[items]="items"
[mode]="mode">
</card-or-list-view>
`
})
export class UsageExample {
mode = 'list';
items = [
{
header: 'Creating Reuseable Components with NgTemplateOutlet in Angular',
content: 'The single responsibility principle...'
} // ... more items
];
}
이 구성 요소는 단일 책임이 없으며 매우 유연하지 않습니다. 모드
를 추적하고 카드
및 목록
보기 모두에서 항목
을 표시하는 방법을 알아야 합니다. 그리고 헤더
와 콘텐츠
가 있는 항목
만 표시할 수 있습니다.
템플릿을 사용하여 구성 요소를 별도의 보기로 나누어 이를 변경해 보겠습니다.
2단계 – ng-template 및 NgTemplateOutlet 이해
CardOrListViewComponent
가 모든 종류의 항목
을 표시할 수 있도록 하려면 표시 방법을 알려줄 수 있어야 합니다. 항목
을 스탬프 처리하는 데 사용할 수 있는 템플릿을 제공하여 이를 달성할 수 있습니다.
템플릿은
를 사용하는 TemplateRefs
이고 스탬프는 TemplateRefs
에서 생성된 EmbeddedViewRefs
입니다. EmbeddedViewRefs
는 자체 컨텍스트가 있는 Angular의 뷰를 나타내며 가장 작은 필수 빌딩 블록입니다.
Angular는 NgTemplateOutlet
을 사용하여 템플릿에서 보기를 스탬프 처리하는 이 개념을 사용하는 방법을 제공합니다.
NgTemplateOutlet
은 TemplateRef
와 컨텍스트를 취하고 제공된 컨텍스트로 EmbeddedViewRef
를 스탬프 처리하는 지시어입니다. 템플릿에서 사용할 수 있는 변수를 생성하기 위해 let-{{templateVariableName}}=\contextProperty\
속성을 통해 템플릿에서 컨텍스트에 액세스합니다. 컨텍스트 속성 이름이 제공되지 않으면 $implicit
속성을 선택합니다.
다음은 예입니다.
import { Component } from '@angular/core';
@Component({
template: `
<ng-container *ngTemplateOutlet="templateRef; context: exampleContext"></ng-container>
<ng-template #templateRef let-default let-other="aContextProperty">
<div>
$implicit = '{{default}}'
aContextProperty = '{{other}}'
</div>
</ng-template>
`
})
export class NgTemplateOutletExample {
exampleContext = {
$implicit: 'default context property when none specified',
aContextProperty: 'a context property'
};
}
다음은 예제의 출력입니다.
<div>
$implicit = 'default context property when none specified'
aContextProperty = 'a context property'
</div>
default
및 other
변수는 let-default
및 let-other=\aContextProperty\
소품에서 제공됩니다.
3단계 – CardOrListViewComponent 리팩터링
CardOrListViewComponent
에 유연성을 제공하고 모든 유형의 항목
을 표시할 수 있도록 템플릿으로 읽을 두 가지 구조 지시문을 만듭니다. 이러한 템플릿은 카드 및 목록 항목이 됩니다.
다음은 card-item.directive.ts
입니다.
import { Directive } from '@angular/core';
@Directive({
selector: '[cardItem]'
})
export class CardItemDirective {
constructor() { }
}
그리고 여기 list-item.directive.ts
가 있습니다:
import { Directive } from '@angular/core';
@Directive({
selector: '[listItem]'
})
export class ListItemDirective {
constructor() { }
}
CardOrListViewComponent
는 CardItemDirective
및 ListItemDirective
를 가져옵니다.
import {
Component,
ContentChild,
Input,
TemplateRef
} from '@angular/core';
import { CardItemDirective } from './card-item.directive';
import { ListItemDirective } from './list-item.directive';
@Component({
selector: 'card-or-list-view',
templateUrl: './card-or-list-view.component.html'
})
export class CardOrListViewComponent {
@Input() items: {
header: string,
content: string
}[] = [];
@Input() mode: string = 'card';
@ContentChild(CardItemDirective, {read: TemplateRef}) cardItemTemplate: any;
@ContentChild(ListItemDirective, {read: TemplateRef}) listItemTemplate: any;
}
이 코드는 구조 지시문에서 TemplateRefs
로 읽힙니다.
<ng-container [ngSwitch]="mode">
<ng-container *ngSwitchCase="'card'">
<ng-container *ngFor="let item of items">
<ng-container *ngTemplateOutlet="cardItemTemplate"></ng-container>
</ng-container>
</ng-container>
<ul *ngSwitchCase="'list'">
<li *ngFor="let item of items">
<ng-container *ngTemplateOutlet="listItemTemplate"></ng-container>
</li>
</ul>
</ng-container>
다음은 이 구성 요소의 사용 예입니다.
import { Component } from '@angular/core';
@Component({
template: `
<card-or-list-view
[items]="items"
[mode]="mode">
<div *cardItem>
Static Card Template
</div>
<li *listItem>
Static List Template
</li>
</card-or-list-view>
`
})
export class UsageExample {
mode = 'list';
items = [
{
header: 'Creating Reuseable Components with NgTemplateOutlet in Angular',
content: 'The single responsibility principle...'
} // ... more items
];
}
이러한 변경으로 CardOrListViewComponent
는 이제 제공된 템플릿을 기반으로 카드 또는 목록 양식에 모든 유형의 항목을 표시할 수 있습니다. 현재 템플릿은 정적입니다.
마지막으로 해야 할 일은 템플릿에 컨텍스트를 제공하여 템플릿을 동적으로 만드는 것입니다.
<ng-container [ngSwitch]="mode">
<ng-container *ngSwitchCase="'card'">
<ng-container *ngFor="let item of items">
<ng-container *ngTemplateOutlet="cardItemTemplate; context: {$implicit: item}"></ng-container>
</ng-container>
</ng-container>
<ul *ngSwitchCase="'list'">
<li *ngFor="let item of items">
<ng-container *ngTemplateOutlet="listItemTemplate; context: {$implicit: item}"></ng-container>
</li>
</ul>
</ng-container>
다음은 이 구성 요소의 사용 예입니다.
import { Component } from '@angular/core';
@Component({
template: `
<card-or-list-view
[items]="items"
[mode]="mode">
<div *cardItem="let item">
<h1>{{item.header}}</h1>
<p>{{item.content}}</p>
</div>
<li *listItem="let item">
{{item.header}}: {{item.content}}
</li>
</card-or-list-view>
`
})
export class UsageExample {
mode = 'list';
items = [
{
header: 'Creating Reuseable Components with NgTemplateOutlet in Angular',
content: 'The single responsibility principle...'
} // ... more items
];
}
주목해야 할 흥미로운 점은 구문 설탕에 별표 접두사와 마이크로 구문을 사용한다는 것입니다. 다음과 동일합니다.
<ng-template cardItem let-item>
<div>
<h1>{{item.header}}</h1>
<p>{{item.content}}</p>
</div>
</ng-template>
그리고 그게 다야! 원래 기능이 있지만 이제 템플릿을 수정하여 원하는 대로 표시할 수 있으며 CardOrListViewComponent
의 책임이 줄어듭니다. ngFor
와 유사한 first
또는 last
와 같은 항목 컨텍스트에 더 많은 것을 추가하거나 완전히 다른 유형의 items
를 표시할 수 있습니다. .
결론
이 문서에서는 기존 구성 요소를 가져와 NgTemplateOutlet
을 사용하도록 다시 작성했습니다.
Angular에 대해 자세히 알아보려면 연습 및 프로그래밍 프로젝트에 대한 Angular 주제 페이지를 확인하세요.