Angular – Gelişmiş Component Yapılanması | ng-content
Merhaba,
Bu içeriğimizde Angular mimarisinde, component’lerin html şablonları içerisine harici içeriklerin yüklenmesini sağlayan ng-content
özelliğini inceliyor olacağız.
Ne Öğreneceğiz?
Biliyorsunuz ki, component’ler arası iletişim için @Input ve @Output dekoratörlerinden istifade edebiliyor ve özellikle parent component’ten child component’e veri aktarmak için @Input dekoratörünü kullanabiliyoruz. Fakat bu dekoratörler eşliğinde component’ler arası iletişim sadece verilerle sınırlıdır. Bazen component’ler arası HTML öğeleri içeren kodlar paylaşmamız ve edinen component tarafından bu kodları render etmemiz gerekebilir. İşte böyle bir durumda ng-content
özelliğinden istifade edebiliriz.
ng-content Nedir?
ng-content
, html içeriklerini parent component’ten child component’e geçirmemizi ve render etmemizi sağlayan, böylece dinamik bir şekilde harici şablonlar oluşturmamıza imkan tanıyan bir özelliktir. İşlevsel olarak child component’in html’inde istenilen noktayı ya da noktaları işaretlememizi sağlayarak parent’tan gelecek olan html öğelerini basmamızı ve yeniden kullanılabilir bir component oluşturmamızı mümkün kılmaktadır.
Misal olarak aşağıdaki component’i ele alırsak eğer;
import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-c1', styleUrls: ['./c1.component.scss'], template: ` <app-c2>Button 1</app-c2> ` }) export class C1Component implements OnInit { constructor() { } ngOnInit(): void { } }
görüldüğü üzere içerisinde <app-c2>...</app-c2>
selector’ı barındırmaktadır ve böylece aşağıdaki component’i çağırmaktadır.
import { Component, Input, OnInit } from '@angular/core'; @Component({ selector: 'app-c2', styleUrls: ['./c2.component.scss'], template: ` <div> <p>Örnek Button</p> <button> <ng-content></ng-content> </button> </div> ` }) export class C2Component implements OnInit { constructor() { } ngOnInit(): void { } }
Bu component’te ise 10. satırda <ng-content></ng-content>
özelliği ile işaretlemede bulunulmuştur. Parent component’in selector arasına koymuş olduğu ‘Button 1’ değeri işte tam da bu noktaya yerleştirilecektir.Netice itibariyle yapılan bu çalışmanın çıktısı yukarıdaki gibi olacaktır.
Multiple ng-content
ng-content
, selector
ile ayrılarak birden fazla olacak şekilde kullanılabilir.
import { Component, Input, OnInit } from '@angular/core'; @Component({ selector: 'app-c2', styleUrls: ['./c2.component.scss'], template: ` <div> <p>Örnek Button</p> <div class="header"> <ng-content select="header"></ng-content> </div> <div class="body"> <ng-content select="body"></ng-content> </div> <div class="footer"> <ng-content select="footer"></ng-content> </div> </div> `, styles: [` .header{ background-color:green; } .body{ background-color:red; } .footer{ background-color:blue; } ` ] }) export class C2Component implements OnInit { constructor() { } ngOnInit(): void { } }
Yukarıdaki kod bloğunu incelerseniz eğer her biri bir selector
‘a sahip üç ng-content
tanımı mevcuttur. Bu selector’ları kullanabilmek için aşağıdaki gibi bir işlem gerçekleştirilmelidir.
import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-c1', styleUrls: ['./c1.component.scss'], template: ` <app-c2> <header>Header Content</header> <body>Body Content</body> <footer>Footer Content</footer> </app-c2> ` }) export class C1Component implements OnInit { constructor() { } ngOnInit(): void { } }
Bu çalışmanın neticesi de yukarıdaki gibi olacaktır.
Ya da isteğiniz doğrultusunda selector
‘ı aşağıdaki gibi CSS seçicisi olarak da kullanabilirsiniz.
import { Component, Input, OnInit } from '@angular/core'; @Component({ selector: 'app-c2', styleUrls: ['./c2.component.scss'], template: ` <div> <div class="header"> <ng-content select=".header"></ng-content> </div> <div class="body"> <ng-content select=".body"></ng-content> </div> <div class="footer"> <ng-content select=".footer"></ng-content> </div> </div> `, styles: [` .header{ background-color:green; } .body{ background-color:red; } .footer{ background-color:blue; } ` ] }) export class C2Component implements OnInit { constructor() { } ngOnInit(): void { } }
Ardından bu css seçicilerine karşılık aşağıdaki gibi değerlerini gönderebilirsiniz.
import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-c1', styleUrls: ['./c1.component.scss'], template: ` <app-c2> <div class="header"> <h1>Header Content</h1> </div> <div class="body"> <h4>Body Content</h4> </div> <div class="footer"> <h6>Footer Content</h6> </div> </app-c2> ` }) export class C1Component implements OnInit { constructor() { } ngOnInit(): void { } }
Sonuç;
Seçici tarafından işaretlenmeyen/belirlenmeyen alanları varsayılan olarak bir noktaya yansıtabilmek için aşağıdaki gibi davranış sergilenebilir.
import { Component, Input, OnInit } from '@angular/core'; @Component({ selector: 'app-c2', styleUrls: ['./c2.component.scss'], template: ` <div> <div class="header"> <ng-content select=".header"></ng-content> </div> <div class="body"> <ng-content select=".body"></ng-content> </div> <div class="footer"> <ng-content select=".footer"></ng-content> </div> <div> <ng-content></ng-content> </div> </div> `, styles: [` .header{ background-color:green; } .body{ background-color:red; } .footer{ background-color:blue; } ` ] }) export class C2Component implements OnInit { constructor() { } ngOnInit(): void { } }
Yukarıdaki kod bloğunu incelerseniz eğer en sonuncu olan ng-content
etiketi eşleşmeyen içerikleri karşılaması için tanımlanmıştır. Misal olarak;
import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-c1', styleUrls: ['./c1.component.scss'], template: ` <app-c2> <div class="header"> <h1>Header Content</h1> </div> <div class="body"> <h4>Body Content</h4> </div> <div class="footer"> <h6>Footer Content</h6> </div> <div> <h6>Diger Content</h6> </div> </app-c2> ` }) export class C1Component implements OnInit { constructor() { } ngOnInit(): void { } }
şeklinde bir veri geldiğinde aşağıdaki gibi bir sonuçla karşılaşılacaktır.
İlgilenenlerin faydalanması dileğiyle…
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…