Derinlemesine yazılım eğitimleri için kanalımı takip edebilirsiniz...

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';
}

Angular - Gelişmiş Component Yapılanması | ng-templateBu 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>

Angular - Gelişmiş Component Yapılanması | ng-templateYukarı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;
}

Angular - Gelişmiş Component Yapılanması | ng-templateGö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.
Angular - Gelişmiş Component Yapılanması | ng-templateAynı 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…

Bunlar da hoşunuza gidebilir...

Bir cevap yazın

E-posta hesabınız yayımlanmayacak.