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…