Detaylı Rehberler
Bileşenler

ng-content ile içerik yansıtma

TIP: Bu rehber, Temel Bilgiler Rehberi'ni zaten okuduğunuzu varsayar. Angular'da yeniyseniz önce onu okuyun.

Farklı içerik türleri için kapsayıcı görevi gören bileşenlere sıklıkla ihtiyaç duyarsınız. Örneğin, özel bir kart bileşeni oluşturmak isteyebilirsiniz:

@Component({
  selector: 'custom-card',
  template: '<div class="card-shadow"> <!-- card content goes here --> </div>',
})
export class CustomCard {
  /* ... */
}

İçeriğin nereye yerleştirileceğini belirtmek için <ng-content> elemanını yer tutucu olarak kullanabilirsiniz:

@Component({
  selector: 'custom-card',
  template: '<div class="card-shadow"> <ng-content/> </div>',
})
export class CustomCard {
  /* ... */
}

TIP: <ng-content>, yerel <slot> elemanı ile benzer şekilde çalışır, ancak bazı Angular'a özgü işlevselliklerle birlikte.

<ng-content> içeren bir bileşen kullandığınızda, bileşen host elemanının tüm alt elemanları o <ng-content> konumunda render edilir veya yansıtılır (project):

// Bileşen kaynağı
@Component({
  selector: 'custom-card',
  template: `
    <div class="card-shadow">
      <ng-content />
    </div>
  `,
})
export class CustomCard {
  /* ... */
}
<!-- Bileşeni kullanma -->
<custom-card>
  <p>This is the projected content</p>
</custom-card>
<!-- Render edilmiş DOM -->
<custom-card>
  <div class="card-shadow">
    <p>This is the projected content</p>
  </div>
</custom-card>

Angular, bu şekilde iletilen bir bileşenin tüm alt elemanlarını o bileşenin içeriği olarak adlandırır. Bu, bileşenin şablonunda tanımlanan elemanlara karşılık gelen bileşenin görünümünden (view) farklıdır.

<ng-content> elemanı ne bir bileşen ne de bir DOM elemanıdır. Bunun yerine, Angular'a içeriği nerede render edeceğini söyleyen özel bir yer tutucudur. Angular'ın derleyicisi tüm <ng-content> elemanlarını derleme zamanında işler. <ng-content> elemanını çalışma zamanında ekleyemez, kaldıramazsınız veya değiştiremezsiniz. <ng-content> üzerine direktifler, stiller veya rastgele nitelikler ekleyemezsiniz.

IMPORTANT: <ng-content> elemanını @if, @for veya @switch ile koşullu olarak dahil etmemelisiniz. Angular, <ng-content> yer tutucusu gizli olsa bile, o yer tutucuya render edilen içerik için her zaman DOM düğümlerini oluşturur ve başlatır. Bileşen içeriğinin koşullu render edilmesi için Şablon parçaları belgesine bakın.

Birden fazla içerik yer tutucusu

Angular, CSS seçicisine dayalı olarak farklı <ng-content> yer tutucularına farklı elemanların yansıtılmasını destekler. Yukarıdaki kart örneğini genişleterek, select niteliği kullanarak kart başlığı ve kart gövdesi için iki yer tutucu oluşturabilirsiniz:

@Component({
  selector: 'card-title',
  template: `<ng-content>card-title</ng-content>`,
})
export class CardTitle {}

@Component({
  selector: 'card-body',
  template: `<ng-content>card-body</ng-content>`,
})
export class CardBody {}
<!-- Bileşen şablonu -->
@Component({
  selector: 'custom-card',
  template: `
  <div class="card-shadow">
    <ng-content select="card-title"></ng-content>
    <div class="card-divider"></div>
    <ng-content select="card-body"></ng-content>
  </div>
  `,
})
export class CustomCard {}
<!-- Bileşeni kullanma -->
@Component({
  selector: 'app-root',
  imports: [CustomCard, CardTitle, CardBody],
  template: `
    <custom-card>
      <card-title>Hello</card-title>
      <card-body>Welcome to the example</card-body>
    </custom-card>
`,
})
export class App {}
<!-- Render edilmiş DOM -->
<custom-card>
  <div class="card-shadow">
    <card-title>Hello</card-title>
    <div class="card-divider"></div>
    <card-body>Welcome to the example</card-body>
  </div>
</custom-card>

<ng-content> yer tutucusu, bileşen seçicileri ile aynı CSS seçicilerini destekler.

select niteliği olan bir veya daha fazla <ng-content> yer tutucusu ve select niteliği olmayan bir <ng-content> yer tutucusu eklerseniz, ikincisi herhangi bir select niteliği ile eşleşmeyen tüm elemanları yakalar:

<!-- Bileşen şablonu -->
<div class="card-shadow">
  <ng-content select="card-title"></ng-content>
  <div class="card-divider"></div>
  <!-- "card-title" dışındaki her şeyi yakala -->
  <ng-content></ng-content>
</div>
<!-- Bileşeni kullanma -->
<custom-card>
  <card-title>Hello</card-title>
  <img src="..." />
  <p>Welcome to the example</p>
</custom-card>
<!-- Render edilmiş DOM -->
<custom-card>
  <div class="card-shadow">
    <card-title>Hello</card-title>
    <div class="card-divider"></div>
    <img src="..." />
    <p>Welcome to the example</p>
  </div>
</custom-card>

Bir bileşen, select niteliği olmayan bir <ng-content> yer tutucusu içermiyorsa, bileşenin yer tutucularıyla eşleşmeyen elemanlar DOM'a render edilmez.

Yedek içerik

Angular, bir bileşenin <ng-content> yer tutucusu için eşleşen alt içerik yoksa yedek içerik gösterebilir. <ng-content> elemanının kendisine alt içerik ekleyerek yedek içerik belirtebilirsiniz.

<!-- Bileşen şablonu -->
<div class="card-shadow">
  <ng-content select="card-title">Default Title</ng-content>
  <div class="card-divider"></div>
  <ng-content select="card-body">Default Body</ng-content>
</div>
<!-- Bileşeni kullanma -->
<custom-card>
  <card-title>Hello</card-title>
  <!-- card-body sağlanmadı -->
</custom-card>
<!-- Render edilmiş DOM -->
<custom-card>
  <div class="card-shadow">
    <card-title>Hello</card-title>
    <div class="card-divider"></div>
    Default Body
  </div>
</custom-card>

Yansıtma için içerik takma adı verme

Angular, herhangi bir eleman üzerinde bir CSS seçici belirtmenize olanak tanıyan özel bir ngProjectAs niteliği destekler. ngProjectAs niteliği olan bir eleman <ng-content> yer tutucusuyla kontrol edildiğinde, Angular elemanın kimliği yerine ngProjectAs değerini karşılaştırır:

<!-- Bileşen şablonu -->
<div class="card-shadow">
  <ng-content select="card-title"></ng-content>
  <div class="card-divider"></div>
  <ng-content />
</div>
<!-- Bileşeni kullanma -->
<custom-card>
  <h3 ngProjectAs="card-title">Hello</h3>

  <p>Welcome to the example</p>
</custom-card>
<!-- Render edilmiş DOM -->
<custom-card>
  <div class="card-shadow">
    <h3>Hello</h3>
    <div class="card-divider"></div>
    <p>Welcome to the example</p>
  </div>
</custom-card>

ngProjectAs yalnızca statik değerleri destekler ve dinamik ifadelere bağlanamaz.

Dikkat edilmesi gerekenler

Projeksiyonlanan içerik, üst bileşenin görünümünde yaşar

Projeksiyonlanan içerik, alıcı bileşenin içinde render edilse de, onu bildiren bileşene aittir. Angular onu üst bileşenin görünümünün bir parçası olarak izler ve bunun bilinmesi gereken birkaç yan etkisi vardır.

Değişiklik algılama: Projeksiyonlanan içerik, üst bileşen değişiklik algılaması çalıştırdığında kontrol edilir. Alıcı bileşen OnPush kullanıyorsa, Angular o bileşenin kendi şablonunu kontrol etmeyi atlayabilir, ancak projeksiyonlanan içeriği atlamaz çünkü o içerik üst bileşene aittir.

<!-- Üst şablon (varsayılan değişiklik algılama) -->
<onpush-wrapper>
  <!-- Her üst döngüde hâlâ kontrol edilir, OnPush burada yardımcı olmaz -->
  <expensive-component />
</onpush-wrapper>

Bağımlılık enjeksiyonu: Projeksiyonlanan içerik bağımlılıklarını, alıcı bileşenin viewProviders'ından değil, üst bileşenin enjektöründen alır. Ayrıntılar için Providers ve viewProviders belgesine bakın.

Bazı kütüphane bileşenleri projeksiyonlanan alt elemanları desteklemez

Bazı bileşenler (menüler, sekmeler, listeler) alt elemanlarını bulmak ve klavye navigasyonu, odak yönetimi veya ARIA öznitelikleri gibi davranışları kurmak için ContentChildren kullanır. Bu bileşenler, alt elemanlarına doğrudan sahip olduklarını varsayarak yazılmıştır, bu nedenle içlerine dışarıdan içerik projeksiyonlamak genellikle işleri ince yollarla bozar.

Örneğin, <mat-menu-item> elemanlarını ekstra bir katmanla sarıp <mat-menu> içine projeksiyonlamak, klavye navigasyonunu ve ekran okuyucu desteğini sessizce bozabilir. Sorgu, elemanları yine de bulur, ancak elemanlar farklı bir görünüm bağlamından geldiğinde, onları etkileşimli kılan iç kurulum doğru çalışmayabilir.

Bir kütüphane bileşeni alt elemanlarının davranışını yönetiyorsa, içerik projeksiyonuna başvurmadan önce belgelerini kontrol edin, desteklenmiyor olabilir.