🔍 Angular Content Projection: Making Components Truly Reusable

If you’ve ever wanted to build highly reusable components without sacrificing flexibility, content projection is your secret weapon. It’s one of those Angular features that can seriously level up your component design once you get the hang of it.

Let’s break down what it is, when to use it, and how to implement both single-slot and multi-slot projection the right way.


đź’ˇ What Exactly Is Content Projection?

At its core, content projection lets you pass HTML content from a parent component into a child component—right where the child component chooses to display it.

This is done using the <ng-content> directive, which acts as a dynamic placeholder in the child template.

Think of it as the Angular version of “insert whatever I give you here.”


đź§  Why Should You Care?

Here’s when content projection becomes a game-changer:

  • âś… Reusable Components: Great for things like cards, modals, dialogs, etc.
  • âś… Separation of Concerns: Keep the component logic separate from the layout.
  • âś… Customization Without Complexity: Parent controls what shows up, child controls how it looks.

đź§Ş Example 1: Single-Slot Content Projection

Let’s start simple. Here’s how you’d build a flexible card component that just wraps around whatever content you give it.

đź”§ card.component.ts (child)

@Component({
selector: 'app-card',
template: `
<div class="card">
<ng-content></ng-content>
</div>
`,
styles: [`
.card {
padding: 20px;
border: 1px solid #ccc;
border-radius: 5px;
}
`]
})
export class CardComponent {}

đź§© app.component.html (parent)

<app-card>
<h3>Welcome</h3>
<p>This card component accepts any content.</p>
</app-card>

Output: A clean, reusable card with whatever content you pass in.


đź§Ş Example 2: Multi-Slot Content Projection

Now let’s level up with multiple content slots—perfect for building things like dialogs or modals with headers, bodies, and footers.

đź”§ dialog.component.ts

@Component({
selector: 'app-dialog',
template: `
<div class="dialog">
<div class="header">
<ng-content select="[dialog-header]"></ng-content>
</div>
<div class="body">
<ng-content select="[dialog-body]"></ng-content>
</div>
<div class="footer">
<ng-content select="[dialog-footer]"></ng-content>
</div>
</div>
`,
styles: [`
.dialog {
border: 1px solid #ccc;
border-radius: 8px;
padding: 20px;
}
.header, .body, .footer {
margin-bottom: 10px;
}
`]
})
export class DialogComponent {}

đź§© app.component.html

<app-dialog>
<div dialog-header>
<h2>Confirm Action</h2>
</div>
<div dialog-body>
<p>Are you sure you want to proceed?</p>
</div>
<div dialog-footer>
<button>Cancel</button>
<button>Yes</button>
</div>
</app-dialog>

This approach keeps your dialog’s structure consistent while letting each instance bring in its own unique content.


âś… Best Practices for Using <ng-content>

🔹 Use multiple slots when you need structured components like tabs, modals, or collapsible panels.

🔹 Pair with @Input() properties to allow even more dynamic behavior alongside projected content.

🔹 Don’t overuse it—too much content projection can make your components harder to reason about. If your template starts feeling like a puzzle, it might be time to rethink your design.


🎯 Final Thoughts

Content projection is one of those Angular features that’s easy to overlook—but once you understand it, it unlocks elegant patterns for building flexible, reusable, and maintainable components.

Whether you’re creating design systems or just trying to DRY up your UI, <ng-content> belongs in your toolkit.

Have a cool use case for content projection or want to combine it with advanced inputs/outputs? Let’s connect and build something modular!

Leave a Comment

Your email address will not be published. Required fields are marked *