Angular – Gelişmiş Component Yapılanması | ng-template
Merhaba,
Bu içeriğimizde Angular mimarisinde tasarımsal açıdan şablonlarla dinamik çalışmalar gerçekleştirmemizi sağlayan ng-template
özelliğini inceliyor olacağız.
ng-template Nedir?
ng-template
, ng-container gibi sayfa üzerinde HTML elementleriyle uğraşmaksızın bir bölüm/alan oluşturmamıza olanak sağlayan ve Document Object Model(DOM) içerisinde tanımlanmayan bir özelliktir. ng-container
‘dan temel farkı, render edildiği taktirde dahi ayrı aparatlar aracılığıyla gösterilmediği sürece içerisindeki HTML elementlerin DOM üzerine işlenmemesidir.
Misal olarak aşağıdaki kod bloğunu incelerseniz eğer;
import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ` <ng-container> Container içerik </ng-container> <ng-template> Template içerik </ng-template> ` }) export class AppComponent { title = 'a'; }
Bu kod render edildiğinde
ng-container
‘ın çıktısının DOM’a eklendiğini lakin ng-template
‘in çıktısının ise eklenmediğini göreceksiniz.
Buradan anlıyoruz ki, ng-template
‘in nerede ve ne zaman görüntüleneceğini bildirmek bizim işimizdir.
ng-template
‘i görüntülemek için aşağıdaki iki yöntemden birini kullanabilirsiniz:
ngTemplateOutlet
direktifi- TemplateRef & ViewContainerRef öğeleri
ngTemplateOutlet Direktifi İle ng-template’i Görüntüleme
<ng-container *ngTemplateOutlet="templateIcerik"> Container içerik </ng-container> <ng-template #templateIcerik> Template içerik </ng-template>
Yukarıdaki kod bloğunu incelerseniz eğer ilgili
ng-template
‘e bir referans atıyoruz ve bu referansı ng-container
üzerinde ‘ngTemplateOutlet’ direktifi eşliğinde çağırıyoruz. Yapılan render neticesine göz atarsanız eğer ng-template
‘in ng-container
içeriğini ezdiğini görüyoruz.
TemplateRef & ViewContainerRef İle ng-template’i Görüntüleme
‘TemplateRef’, ng-template
‘i component üzerinde(.ts) temsil etmemizi sağlayan bir sınıfken, ‘ViewContainerRef’ ise ng-template
‘in nerede oluşturulacağını belirtmemizi sağlayan başka bir sınıftır.
import { AfterViewInit, Component, TemplateRef, ViewChild, ViewContainerRef } from '@angular/core'; @Component({ selector: 'app-root', template: ` <ng-template #templateIcerik> Template içerik </ng-template> ` }) export class AppComponent implements AfterViewInit { constructor(private viewContainerRef: ViewContainerRef) { } @ViewChild("templateIcerik", { read: TemplateRef }) templateIcerik: TemplateRef<any>; ngAfterViewInit(): void { this.viewContainerRef.createEmbeddedView(this.templateIcerik); } }
Yukarıdaki kod bloğuna göz atarsanız eğer ng-template
‘e yine bir referans verilmekte ve component’in .ts dosyası içerisinde ‘@ViewChild’ eşliğinde bu referans ‘TemplateRef’ türünde elde edilmektedir. Ardından dependency injection ile inject edilen ‘ViewContainerRef’ nesnesi üzerinden createEmbeddedView
metodu kullanılarak ng-template
sayfada görüntülenmektedir.
Evet, artık ng-template
‘in ne olduğunu ve nasıl kullanıldığını öğrendiğimize göre gelin hangi durumlarda tercih edebileceğimizi inceleyelim.
ngIf İle ng-template Kullanımı
ngIf direktifini aşağıdaki gibi bir durumda birçok kez kullanmışsınızdır.
import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ` <input [(ngModel)]="selected" type="checkbox"> Seç <div *ngIf="selected"> Seçili </div> ` }) export class AppComponent { selected: boolean = false; }
Bu kodu yazmanın aşağıdaki gibi ng-template
eşliğinde farklı bir yolu daha vardır.
import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ` <input [(ngModel)]="selected" type="checkbox"> Seç <ng-template [ngIf]="selected"> <div> Seçili </div> </ng-template> ` }) export class AppComponent { selected: boolean = false; }
Ya da aşağıdaki gibi if-else durumlarına göre şablon gösterimlerinde ng-template
biçilmiş kaftandır.
import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ` <div *ngIf="selected; then template1 else template2"> </div> <ng-template #template1> Şablon 1 </ng-template> <ng-template #template2> Şablon 2 </ng-template> ` }) export class AppComponent { selected: boolean = true; }
Görüldüğü üzere şarta göre hangi
ng-template
‘in görüntüleneceğini if -> then -> else yapısı sayesinde belirlememizi sağlamaktadır. Ayrıca ilgili HTML elemanının yerine şarta uygun referansa karşılık gelen ng-template
‘in içeriğini bastığına dikkatinizi çekerim.
Tabi yukarıdaki çalışmayı aşağıdaki gibi [ngIf]
, [ngIfThen]
ve [ngIfElse]
direktifleri eşliğinde de geliştirebiliriz.
import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ` <ng-template [ngIf]="selected" [ngIfThen]="template1" [ngIfElse]="template2"> </ng-template> <ng-template #template1> Şablon 1 </ng-template> <ng-template #template2> Şablon 2 </ng-template> ` }) export class AppComponent { selected: boolean = true; }
ngFor İle ng-template Kullanımı
Aşağıdaki ngFor direktifiyle olan çalışmayı ele alırsak eğer;
import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ` <ul> <li *ngFor="let product of products;trackBy: trackByProduct"> {{ product.name }} </li> </ul> ` }) export class AppComponent { products: { name: string, quantity: number }[] = [ { name: "A Product", quantity: 15 }, { name: "B Product", quantity: 25 }, { name: "C Product", quantity: 35 }, { name: "D Product", quantity: 45 } ] trackByProduct(index, product: { name: string, quantity: number }) { return product.name; } }
ng-template
eşliğinde aşağıdaki gibi de inşa edebilirsiniz.
<ul> <ng-template ngFor let-product [ngForOf]="products" [ngForTrackBy]="trackByProduct"> <li> {{ product.name }} </li> </ng-template> </ul>
Burada görüldüğü üzere ngFor
, [ngForOf]
ve [ngForTrackBy]
direktifleri bizlere eşlik etmektedir.
ngSwitch İle ng-template Kullanımı
ng-template
‘i aynı şekilde ngSwitch
ile birlikte de kullanabilmekteyiz. Şöyle ki;
import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ` <input type="number" [(ngModel)]="number" max="5" min="1"> <div [ngSwitch]="number"> <div *ngSwitchCase="1">Bir</div> <div *ngSwitchCase="2">İki</div> <div *ngSwitchCase="3">Üç</div> <div *ngSwitchCase="4">Dört</div> <div *ngSwitchCase="5">Beş</div> </div> ` }) export class AppComponent { number: number; }
Yukarıdaki örneği ele alırsak render edildiğinde aşağıdaki gibi bir çalışma sergileyecektir.
Aynı operasyonu
ng-template
ile aşağıdaki gibi gerçekleştirirsek eğer aynı davranışı sergilemiş olacaktır.
<input type="number" [(ngModel)]="number" max="5" min="1"> <div [ngSwitch]="number"> <ng-template [ngSwitchCase]="1"> <div>Bir</div> </ng-template> <ng-template [ngSwitchCase]="2"> <div>İki</div> </ng-template> <ng-template [ngSwitchCase]="3"> <div>Üç</div> </ng-template> <ng-template [ngSwitchCase]="4"> <div>Dört</div> </ng-template> <ng-template [ngSwitchCase]="5"> <div>Beş</div> </ng-template> <ng-template ngSwitchDefault> <div>Sıfır</div> </ng-template> </div>
İlgilenenlerin faydalanması dileğiyle…
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…