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.
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() →