Content projection (ng-content) in Angular
What is Content Projection?
Content projection allows you to pass HTML content from a parent component into a child component's template. It's Angular's equivalent of React's children or Vue's slots.
Single-Slot Projection
typescript
// card.component.ts
@Component({
selector: 'app-card',
standalone: true,
template: \`
<div class="card">
<div class="card-body">
<ng-content></ng-content>
</div>
</div>
\`
})
export class CardComponent {}html
<!-- Usage -->
<app-card>
<h2>Card Title</h2>
<p>Any content can go here!</p>
<button>Action</button>
</app-card>Multi-Slot Projection
Use select attribute to project content into specific slots:
typescript
@Component({
selector: 'app-dialog',
template: \`
<div class="dialog">
<header>
<ng-content select="[dialog-header]"></ng-content>
</header>
<main>
<ng-content select="[dialog-body]"></ng-content>
</main>
<footer>
<ng-content select="[dialog-footer]"></ng-content>
</footer>
</div>
\`
})
export class DialogComponent {}html
<app-dialog>
<div dialog-header>
<h2>Confirm Delete</h2>
</div>
<div dialog-body>
<p>Are you sure you want to delete this item?</p>
</div>
<div dialog-footer>
<button (click)="cancel()">Cancel</button>
<button (click)="confirm()">Delete</button>
</div>
</app-dialog>Select Options
html
<!-- By attribute -->
<ng-content select="[header]"></ng-content>
<!-- By CSS class -->
<ng-content select=".footer"></ng-content>
<!-- By element -->
<ng-content select="h2"></ng-content>
<!-- By component -->
<ng-content select="app-icon"></ng-content>
<!-- Default (unmatched content) -->
<ng-content></ng-content>Conditional Projection with ng-template
typescript
@Component({
selector: 'app-expandable',
template: \`
<div class="header" (click)="toggle()">
<ng-content select="[title]"></ng-content>
</div>
<div class="body" *ngIf="isOpen">
<ng-content select="[content]"></ng-content>
</div>
\`
})
export class ExpandableComponent {
isOpen = false;
toggle() { this.isOpen = !this.isOpen; }
}ContentChild and ContentChildren
Access projected content programmatically:
typescript
@Component({ /* ... */ })
export class TabsComponent implements AfterContentInit {
@ContentChildren(TabComponent) tabs!: QueryList<TabComponent>;
ngAfterContentInit() {
// Access projected tab components
const activeTabs = this.tabs.filter(tab => tab.active);
if (activeTabs.length === 0) {
this.tabs.first.active = true;
}
}
}html
<app-tabs>
<app-tab title="Home">Home content</app-tab>
<app-tab title="Settings">Settings content</app-tab>
<app-tab title="Profile" [active]="true">Profile content</app-tab>
</app-tabs>Important:
Content projection with <ng-content> lets you create flexible, reusable wrapper components (cards, dialogs, layouts). Use select for multi-slot projection. Use @ContentChildren to access projected components programmatically. It's Angular's version of React's children prop or Vue's slots.
Short Answer
Interview readyPremium
A concise answer to help you respond confidently on this topic during an interview.