LearnAI ToolsCareerPractice BuildsPlayContact
Lesson 1615 min read

Content Projection (ng-content)

Pass markup into a component using ng-content, including multi-slot projection with select.

Basic Content Projection

An <ng-content> element inside a component's template marks a spot where the parent can inject its own markup — Angular's equivalent of a slot.

// card.component.ts
@Component({
selector: 'app-card',
standalone: true,
template: `
<div class="card">
<ng-content />
</div>
`,
})
export class CardComponent {}
<!-- Parent template -->
<app-card>
<h3>Product Name</h3>
<p>Product description goes here.</p>
</app-card>

Multi-Slot Projection with select

Multiple <ng-content> elements, each with a select attribute matching a CSS selector, let a component define several distinct insertion points.

// layout.component.ts
@Component({
selector: 'app-layout',
standalone: true,
template: `
<header><ng-content select="[header]" /></header>
<main><ng-content /></main>
<footer><ng-content select="[footer]" /></footer>
`,
})
export class LayoutComponent {}
<!-- Parent template -->
<app-layout>
<h1 header>My Site</h1>
<p>Main page content goes into the default (unselected) slot.</p>
<p footer>&copy; 2026</p>
</app-layout>
select Matches Any CSS Selector

select="[header]" matches an attribute, but it can just as easily match a tag name (select="h1") or a class (select=".highlight") — whatever CSS selector best identifies the content that belongs in that slot.

Fallback Content

Unlike some frameworks' slot systems, plain <ng-content> does not support inline fallback content directly — if you need a default, conditionally show your own fallback markup based on whether ng-content has projected content, typically checked via a ContentChild query.

Common Beginner Mistakes

Reaching for @Input when you actually need projected markup

If the parent needs to pass arbitrary HTML or components (not just data), ng-content is the right tool — an @Input can only carry data values, not template structure.

Forgetting that unselected content still needs a plain <ng-content> to land somewhere

Any content that doesn't match a select attribute needs an unselected <ng-content /> present, or it's simply dropped.

FAQs

The default, unselected <ng-content /> is conceptually similar; the select attribute goes further, letting you target multiple distinct insertion points by CSS selector.

Yes — a @ContentChild or @ContentChildren query lets a component inspect or interact with its own projected content programmatically.

Summary

ng-content lets a parent inject markup into specific places inside a child's template, with the select attribute enabling multiple named insertion points. Next, you'll learn the lifecycle hooks available on every Angular component.

Next Lesson →

Lifecycle Hooks