Angular – Gelişmiş Component Yapılanması | ngTemplateOutlet
Merhaba,
Bu içeriğimizde Angular mimarisinde bir structural directive olan ngTemplateOutlet direktifinin ne olduğunu ve nasıl kullanıldığını tam teferruatlı ele alıyor olacağız.
ngTemplateOutlet Neye Yarar?
DOM üzerinde ng-container ile ayrılmış çeşitli bölümlere ng-template‘in barındırdığı içerikleri yayınlamak için kullanılmaktadır.
ngTemplateOutlet Nasıl Kullanılır?
Bunu önceden klavyeye almış olduğumuz ng-container ve ng-template başlıklı içeriklerimizde basitinden incelemiştik. Yine benzer örneği vermemiz gerekirse eğer aşağıdaki kod bloğunu inceleyiniz:
<div style="background-color:pink;"> <ng-container *ngTemplateOutlet="contentTemplate"> </ng-container> </div> <ng-template #contentTemplate> Content... </ng-template>
ngTemplateOutlet’i ngTemplateOutletContext İle Kullanmak?
ngTemplateOutlet‘e ngTemplateOutletContext özelliğini kullanarak da ekstradan parametrik veriler iletebiliriz. Şöyle ki;
<div style="background-color:pink;">
<ng-container [ngTemplateOutlet]="contentTemplate" [ngTemplateOutletContext]="{data:{value:15}}">
</ng-container>
</div>
<ng-template #contentTemplate let-data="data">
Content...
{{data.value}}
</ng-template>
Yukarıdaki kod bloğunu incelerseniz ‘contentTemplate’ isminde bir şablon oluşturulmakta ve ng-container üzerinden bu şablona [ngTemplateOutletContext] eşliğinde
yandaki json değeri parametre olarak gönderilmektedir. ng-template ise bu parametreyi let-data keyword’ü ile yakalamakta ve içerisinde kullanmaktadır. Burada dikkat edilmesi gereken bir husus vardır ki o da, let-data içerisinde belirtilecek parametre adının [ngTemplateOutletContext]‘e verilen json datasındaki ilk değer ile aynı olması zaruriyetidir.
Ayrıca alternatif olarak aşağıdaki sözdizimini de kullanabilirsiniz.
<ng-container *ngTemplateOutlet="contentTemplate; context:{data: {value: 15}}" >
</ng-container>
Eğer birden fazla parametrik değer göndermek istiyorsanız aşağıdaki gibi çalışabilirsiniz.
<div style="background-color:pink;">
<ng-container [ngTemplateOutlet]="contentTemplate" [ngTemplateOutletContext]="{data1:{value:15}, data2:{value:25}, data3:{value:35}}" >
</ng-container>
</div>
<ng-template #contentTemplate
let-data1="data1"
let-data2="data2"
let-data3="data3">
Content...
{{data1.value}}<br>
{{data2.value}}<br>
{{data3.value}}
</ng-template>
Ya da diğer sözdizimine göre aşağıdaki gibi de çalışabilirsiniz.
<ng-container *ngTemplateOutlet="contentTemplate; context: {data1:{value:15}, data2:{value:25}, data3:{value:35}}" >
</ng-container>
$implicit Kullanımı?
$implicit keyword’ünü context nesnesinde kullanırsanız eğer tüm local değişkenler için default değer olarak ayarlama gerçekleştirebilirsiniz. Misal olarak aşağıdaki örnekte, let-default‘a herhangi bir değer ataması gerçekleştirmedik. Bundan dolayı ilgili parametre değerini $implicit parametresinden alacaktır.
<div style="background-color:pink;">
<ng-container [ngTemplateOutlet]="contentTemplate" [ngTemplateOutletContext]="{$implicit: 'default value', data: {value:15}}" >
</ng-container>
</div>
<ng-template #contentTemplate let-data="data" let-default>
Content...
{{data.value}} <br>
{{default}}
</ng-template>
Bizler $implicit keyword’ünü genellikle tekil parametrelerin söz konusu olduğu durumlar için pratik olduğu düşüncesiyle tercih ederiz. Bunun için aşağıdaki örneği inceleyebilirsiniz;
import { Component } from '@angular/core';
@Component({
selector: 'app-persons',
template: `
<ng-container [ngTemplateOutlet]="personTemplate" [ngTemplateOutletContext]="{$implicit: persons}">
</ng-container>
<ng-template let-persons #personTemplate>
<ul>
<li *ngFor="let person of persons">
{{person.name}} {{person.surname}}
</li>
</ul>
</ng-template>
`
})
export class PersonsComponent {
persons: { name: string, surname: string }[] = [
{ name: "Gençay", surname: "Yıldız" },
{ name: "Nevin", surname: "Yıldız" },
{ name: "Gülşah", surname: "Yıldız" },
{ name: "Muhammet Kürşad", surname: "Yıldız" },
]
}
Görüldüğü üzere buradaki operasyonda direkt ng-container içerisinde çağrılacak template içerisine persons dizisi tek bir parametre olarak gönderilmek istenmekte ve bunun için ayrı bir alanı manuel olarak tanımlamak yerine direkt olarak $implicit keyword’ü ile default tanımlama gerçekleştirilmektedir. Devamında ise ng-template‘te kullanırken direkt olarak let-persons adında bir değişkenle(ki farklı bir isimde de olabilirdi) veri elde edilmektedir.

Child Component’e Template Geçirmek
ngTemplateOutlet‘i kullanarak parent component’ten child component’e template’leri geçirebilir ve istediğimiz yerlerde kullanabiliriz. Bunun için aşağıdaki örneği inceleyiniz;
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-parent',
template: `
<ng-template #parentTemplate>
Parent Component Template Content
</ng-template>
<app-child [childTemplate]="parentTemplate"></app-child>
`
})
export class ParentComponent {
}
Yukarıda parent component’in içeriğine göz atarsanız eğer ‘parentTemplate’ adında bir ng-template tanımlanmıştır ve bu template, 10. satırda selector’ı ile çağrılan child component’in ‘childTemplate’ değerine gönderilmiştir. Şimdi de aşağıda child component’in içeriğine göz atarsak;
import { Component, Input, OnInit, TemplateRef } from '@angular/core';
@Component({
selector: 'app-child',
template: `
<ng-container *ngTemplateOutlet="childTemplate">
</ng-container>
`
})
export class ChildComponent {
@Input() childTemplate: TemplateRef<HTMLElement>;
}
Burada da ng-container‘a ngTemplateOutlet ile bir ‘TemplateRef<HTMLElement>’ türünden ‘childTemplate’ isimli input parametre bağlanmıştır. Bu parametre işte parent component’te 10. satırdaki ‘[childTemplate]’e karşılık gelmektedir.
Yapılan bu çalışma neticesinde parent component’te ki template child component’e geçirilmiştir.
ViewChild Kullanarak Template’e Erişmek
Herhangi bir component’te ki ng-template‘e erişim sağlayabilmek için aşağıdaki gibi ‘ViewChild’ı kullanabilirsiniz.
import { AfterViewInit } from '@angular/core';
import { TemplateRef, ViewChild } from '@angular/core';
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
<ng-template #myTemplate>
Template content
</ng-template>
`
})
export class AppComponent implements AfterViewInit {
@ViewChild("myTemplate") myTemplate: TemplateRef<HTMLElement>;
ngAfterViewInit(): void {
console.log(this.myTemplate);
}
}
ng-template’i ng-content İle Birlikte Kullanmak
Parent ve child component’lerin söz konusu olduğu durumlarda ng-content‘i aşağıdaki gibi ng-template içerisinde kullanabilirsiniz.
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-parent',
template: `
<app-child>
<p>Bu içerik ng-content için</p>
</app-child>
`
})
export class ParentComponent {
}
import { Component, Input, OnInit, TemplateRef } from '@angular/core';
@Component({
selector: 'app-child',
template: `
<ng-container [ngTemplateOutlet]="myTemplate">
</ng-container>
<ng-template #myTemplate>
<ng-content></ng-content>
</ng-template>
`
})
export class ChildComponent {
}
İlgilenenlerin faydalanması dileğiyle…
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…


Çok dolu bir içerik olmuş elinize sağlık
Çok açıklayıcı ve dolu bir yazı olmuş, elinize emeğine sağlık!