ng-template
< ng-template >엘리먼트는 앵귤러가 사용하는 템플릿 엘리먼트로서 내부 요소노드를 랜더링하지 않게 만드는 기능을 한다.
<ng-template >
<div>Hello</div>
</ng-template>
랜더링되지 않을뿐아니라 DOM에 추가되지 않는다. 따라서 랜더링하지 않아야 할 요소노드가 있다면 ng-template엘리먼트를 사용하면 된다.
내부 요소노드를 랜더링(DOM추가)하려면 어떻게 해야 할까?
ngIf 구조디렉티브를 사용하면 된다.
<ng-template [ngIf]="true">
<div>Hello</div>
</ng-template>
ngIf 디렉티브에 boolean값을 바인딩하여 참이면 랜더링된다.
ng-template는 템플릿내 요소노드의 랜더링여부를 결정하는 앵귤러가 사용하는 엘리먼트다.
<p>Hip!</p>
<ng-template>
<p>Hip!</p>
</ng-template>
<p>Hooray!</p>
< ng-template >내부에 있는 노드는 주석처리되어 랜더링되지 않는다.
< ng-template >의 용도는 구조디렉티브를 사용하여 랜더링될 컨텐츠를 보유하는 것이다.
구조디렉티브는 보유 템플릿의 복사본을 추가하거나 제거할 수 있다.
< ng-template>엘리먼트는 TemplateRef클래스의 인스턴스이며 보유템플릿을 DOM에 추가하기위해 ViewContainerRef클래스의 메소드인 createEmbeddedView()를 사용한다.
< ng-template>은 템플릿변수를 사용할 수 있기 때문에 ngIf else구문으로 참조가능하다.
<div *ngIf=”true”> Hi </div>
ngIf가 true로 평가되므로 div요소노드가 DOM에 추가되고 랜더링되어 Hi문자열이 보인다.
앵귤러는 위템플릿코드를 아래와같이 변환후 처리한다.
<ng-template [ngIf]=”true”>
<div> Hi </div>
</ng-template>
< ng-template >은 앵귤러 구조디렉티브가 템플릿을 가공하기위해 사용하는 TemplateRef인스턴스인 것이다.
<ng-template [ngIf]=”true”> ngif </ng-template>
HTML요소노드없이 바로 ng-template와 구조디렉티브를 사용할 수 있고 이때는 바인딩해야한다. 텍스트노드가 만들어진다.
<div *ngIf=”true; then tplvar”></div>
<ng-template #tplvar>
template reference variable
</ng-template>
div는 ngIf...then 역활만하고 참평가시 ng-template엘리먼트가 랜더링되고 div는 없어진다.
<ng-template [ngIf]=”true”> Hi </ng-template>
<ng-template *ngIf=”true”> Hi </ng-template>
ng-template은 [ngIf]='true'처럼 바인딩문법을 사용해야 한다.
<ng-template [ngIf]="true">
<ng-template> Hi </ng-template>
</ng-template>
*ngIf를 사용하면 제대로 랜더링되지 않는다.
ng-container
ng-template은 랜더링될수도 있고 안될수도 있는 엘리먼트이지만 ng-container는 랜더링되는 엘리먼트이므로 사용법이 기본적으로 다르다.
<ng-container> Hi </ng-container>
ng-container엘리먼트는 기본적으로 랜더링된다.
<ng-container *ngIf=”true” > Hi </ng-container>
ng-container엘리먼트는 *ngIf간략구문을 사용할 수 있다.
<div *ngIf=”isClicked”> 버튼이 눌림!! </div>
<button (click)=”isClicked=!isClicked”>button </button>
버튼클릭에따라 div요소노드는 DOM에 추가되고 삭제된다.
<ng-container *ngIf=”isClicked”> 버튼이 눌림!! </ng-container>
<button (click)=”changeStatus()”>button </button>
ng-container는 요소노드가 아닌 텍스트노드로 DOM에 추가되거나 삭제된다.
<div *ngFor="let item of [{id:1},{id:2}]">
<div *ngIf="item.id">
{{item.id}}
</div>
</div>
ngFor div내에 div가 존재하게 된다.
<ng-container *ngFor="let item of [{id:1},{id:2}]">
<div *ngIf="item.id">
{{item.id}}
</div>
</ng-container>
내부div만 존재하고 ng-container는 사라지므로 메모리효율면에서 좋다.
ngTemplateOutlet
만들어진 TemplateRef인스턴스(< ng-template >)를 사용하여 뷰를 추가한다.
ng-container에 ngTemplateOutlet디렉티브를 사용할 수 있다.
<ng-container *ngTemplateOutlet=”template”></ng-container>
<ng-template #template> Hello!</ng-template>
ngTemplateOutlet디렉티브의 용도는 만들어진 < ng-template #tpl >를 사용하여 여러곳에 사용할때 유용하다.
*ngTemplateOutlet와 [ngTemplateOutlet]은 같다.
<div>헤더
<ng-container *ngTemplateOutlet="logo"></ng-container>
</div>
<div>본문
<ng-container *ngTemplateOutlet="logo"></ng-container>
</div>
<div>푸터
<ng-container *ngTemplateOutlet="logo"></ng-container>
</div>
<ng-template #logo>
<img src="../../favicon.ico">
</ng-template>
logo템플릿변수를 여러곳에 사용할때 유용하다.
<ng-container *ngTemplateOutlet="greet"></ng-container>
<hr>
<ng-container *ngTemplateOutlet="eng; context: myContext"></ng-container>
<hr>
<ng-container *ngTemplateOutlet="svk; context: myContext"></ng-container>
myContext = {$implicit: 'World', localSk: 'Svet'};
<hr>
<ng-template #greet><span>Hello</span></ng-template>
<ng-template #eng let-name><span>Hello {{name}}!</span></ng-template>
<ng-template #svk let-person="localSk"><span>Ahoj {{person}}!</span></ng-template>
ng-template에 템플릿변수, 클래스프로퍼티로 데이터를 가져올 수 있다.