Episode 9 of 27
Ng-Content Directive
Use ng-content for content projection — pass HTML content from a parent component into a child component's template.
Ng-Content Directive
<ng-content> allows you to project content from a parent component into a child component. Think of it as a "slot" where parent HTML gets inserted.
The Problem
<!-- Parent template -->
<app-card>
<h3>This content is IGNORED!</h3>
<p>Nothing between the tags shows up.</p>
</app-card>
<!-- Card template -->
<div class="card">
<!-- Where does the parent content go? Nowhere! -->
</div>
The Solution: ng-content
<!-- card.component.html -->
<div class="card">
<ng-content></ng-content> <!-- Parent content is projected HERE -->
</div>
<!-- Parent template -->
<app-card>
<h3>Card Title</h3>
<p>This content now appears inside the card!</p>
</app-card>
<!-- Rendered result: -->
<div class="card">
<h3>Card Title</h3>
<p>This content now appears inside the card!</p>
</div>
Reusable Card Component
// card.component.ts
@Component({
selector: 'app-card',
template: `
<div class="card">
<ng-content></ng-content>
</div>
`,
styles: [`
.card {
background: white;
border-radius: 12px;
padding: 24px;
box-shadow: 0 2px 12px rgba(0,0,0,0.08);
margin-bottom: 20px;
}
`]
})
<!-- Now use it with ANY content: -->
<app-card>
<h3>User Profile</h3>
<p>Name: Alice Johnson</p>
</app-card>
<app-card>
<h3>Statistics</h3>
<ul>
<li>Posts: 42</li>
<li>Followers: 1,200</li>
</ul>
</app-card>
Multi-Slot Projection
Use the select attribute to project content into specific slots:
<!-- panel.component.html -->
<div class="panel">
<div class="panel-header">
<ng-content select="[panel-header]"></ng-content>
</div>
<div class="panel-body">
<ng-content select="[panel-body]"></ng-content>
</div>
<div class="panel-footer">
<ng-content select="[panel-footer]"></ng-content>
</div>
</div>
<!-- Parent usage: -->
<app-panel>
<div panel-header>
<h2>Settings</h2>
</div>
<div panel-body>
<p>Configure your preferences here.</p>
</div>
<div panel-footer>
<button>Save</button>
</div>
</app-panel>
Select Options
| Selector | Matches |
|---|---|
select="h2" | Element: <h2> |
select=".header" | Class: <div class="header"> |
select="[panel-header]" | Attribute: <div panel-header> |
select="app-title" | Component: <app-title> |
Default Slot (Catch-All)
<!-- A ng-content without select catches everything else: -->
<div class="card">
<div class="card-header">
<ng-content select="[card-title]"></ng-content>
</div>
<div class="card-body">
<ng-content></ng-content> <!-- Everything else goes here -->
</div>
</div>
Key Takeaways
<ng-content>creates a slot where parent HTML is projected into the child- Without
ng-content, content between component tags is discarded - Use
selectfor multi-slot projection — target by element, class, or attribute - A plain
<ng-content>withoutselectis the default catch-all slot - Content projection is essential for building reusable wrapper components