Content Projection With ng-content

Let a Parent Pass Markup Into a Slot

Content Projection With ng-content

The ng-content element renders whatever children the parent placed inside the component tag — Angular's version of slot composition.

4 min read Level 2/5 #angular#components#projection
What you'll learn
  • Single-slot projection with ng-content
  • Multi-slot projection with select
  • Combine projection with control flow

Sometimes a component needs to wrap arbitrary markup — a card wrapping any content, a modal wrapping any body. That is content projection.

Single-Slot Projection

import { Component } from '@angular/core';

@Component({
  selector: 'app-card',
  standalone: true,
  template: `<div class="card"><ng-content /></div>`,
})
export class CardComponent {}

Use it from a parent:

<app-card>
  <h2>Hello</h2>
  <p>Anything in here is projected.</p>
</app-card>

Multi-Slot Projection

Use a select attribute on ng-content to route different children into different slots.

@Component({
  selector: 'app-card',
  standalone: true,
  template: `
    <header><ng-content select="[card-header]" /></header>
    <main><ng-content /></main>
    <footer><ng-content select="[card-footer]" /></footer>
  `,
})
export class CardComponent {}
<app-card>
  <div card-header>Title</div>
  <p>Body content goes in the default slot.</p>
  <div card-footer>Actions</div>
</app-card>

Conditional Projection

Wrap a projection in @if to make a slot optional.

@if (showHeader()) {
  <header><ng-content select="[card-header]" /></header>
}

Projected content is rendered in the parent’s injection scope, so its lifecycle and change detection belong to the parent.

viewChild() & contentChild() →