Skip to main content
Content Projection

Content Projection Overview

Estimated Time: 2 hours | Difficulty: Intermediate | Prerequisites: Components, Templates
Content projection allows you to create flexible, reusable components by inserting content from a parent component into designated slots in the child component. The analogy is a picture frame: the frame (child component) provides the structure and styling, but the picture (projected content) comes from whoever uses the frame. This is the fundamental pattern behind every reusable layout component — cards, modals, tabs, accordions, and data tables. Why this matters: Without content projection, you end up with one of two bad outcomes: either your components are too rigid (hard-coded templates that cannot be customized) or too flexible (accepting dozens of inputs to cover every variation). Content projection hits the sweet spot — the component controls the layout and behavior, while the consumer controls the content.

Single-Slot Projection


Multi-Slot Projection

Using select Attribute

Multi-slot projection uses CSS-like selectors on <ng-content> to route projected content into the right slot. The select attribute accepts element names, CSS classes, and attribute selectors. Any projected content that does not match a select goes into the default (un-selected) <ng-content> slot. This is analogous to named slots in Vue or React’s children vs named props pattern.

Using CSS Selectors


ng-template with Content Projection

ng-template combined with ngTemplateOutlet is the Angular equivalent of React’s “render props” pattern. The parent provides a template (the “how to render each item”) and the child provides the data and controls when to render it. This inverts the typical control flow: the child component decides when and where to render, while the parent decides what to render. It is the ultimate tool for building highly flexible components like tabs, tables, and lists.
Practical tip: When a component accepts a TemplateRef input, always provide a sensible default template using a local ng-template with #defaultTemplate. This way, the component works out of the box without requiring the consumer to always pass a custom template.

ContentChild & ContentChildren

@ContentChild and @ContentChildren let a component inspect and interact with the content projected into it. Think of a playlist app: the playlist component (parent) does not just display songs (projected children) — it also needs to know about them to handle “play next” logic, enforce “only one song playing at a time,” or reorder them. @ContentChildren gives the parent a QueryList of projected child components, enabling exactly this kind of coordination.

Conditional Content Projection


ngProjectAs

ngProjectAs solves a subtle problem: what if you want to project a component or ng-container into a named slot, but its tag name or attributes do not match the slot’s select selector? ngProjectAs lets you tell Angular “treat this element as if it had the specified selector.” It is like giving a backstage pass to someone whose name is not on the guest list — you are vouching that they belong in that slot.

Context-Aware Projection


Advanced: Render Props Pattern


Best Practices

Name Slots Clearly

Use descriptive attribute names for multi-slot projection

Provide Defaults

Use fallback content when projection is optional

Document Slots

Document expected content in component API

Type Templates

Use generics for type-safe template contexts

Next: Dynamic Components

Learn to create and manage dynamic components