Use <ng-content> to render content that a caller places inside your component’s tags. Add one placeholder to pass all child content through, or use placeholders with select to route content into named slots. The projected markup remains part of the parent’s view; the receiving component decides where it appears.
How basic content projection works
<ng-content> marks a location in a component template where Angular renders child content supplied by the caller. It is a special placeholder, not a component or a real DOM element. Angular processes it at build time.
As an Amazon Associate I earn from qualifying purchases.
For a simple wrapper, put one placeholder in the component template:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
<!-- wrapper.component.html -->
<section class="panel">
<ng-content />
</section>
A parent can then supply the content between the component’s opening and closing tags:
#1 Best Overall
<app-wrapper>
<p>This paragraph appears inside the panel.</p>
</app-wrapper>
Use a single placeholder when every supplied child belongs in the same location. For Angular’s overview, see Content projection with ng-content and the ng-content API reference.
How to create multiple slots
Add more than one placeholder and give named slots a select attribute. Angular supports CSS selectors such as element names, attributes, classes, and :not(). A card can route content carrying a card-title attribute to its heading while placing unmatched content in the body:
Rank #2
<!-- card.component.html -->
<article class="card">
<h2><ng-content select="[card-title]" /></h2>
<div class="card-body">
<ng-content />
</div>
</article>
Caller markup can match the selector directly:
<app-card>
<span card-title>Account settings</span>
<p>Change your profile details here.</p>
</app-card>
The selected placeholder receives matching elements. The unselected placeholder receives elements that did not match a selected slot. If the template has selected placeholders but no unselected one, unmatched child content does not render in the component’s DOM.
For more on selectors and placeholder behavior, consult Angular’s ng-content template guide.
Rank #3
What to do when content does not match a slot
Check the selector against the supplied element
A slot selected with [card-title] needs a matching attribute on the projected element. Confirm the caller supplies that attribute, class, or element name exactly as the selector expects.
Use ngProjectAs for a static alias
If the caller’s element cannot use the selector directly, add ngProjectAs to make Angular treat it as though it matched a selector. For example:
Rank #4
<app-card>
<h3 ngProjectAs="[card-title]">Account settings</h3>
<p>Change your profile details here.</p>
</app-card>
ngProjectAs is static; it cannot be dynamically bound.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Fix the driver behind crashes, sound loss and screen glitches3Clear out junk files and repair common Windows errorsCheck control-flow blocks with multiple root nodes
Angular’s NG8011 diagnostic explains a less obvious mismatch: a control-flow block determines projection using its root element. If a block has multiple root nodes, content intended for a named slot may instead land in the default slot. One documented fix is to put the content in an ng-container with a matching ngProjectAs alias; another is to split the content into blocks with one projectable root each. See NG8011: Control flow preventing content projection.
How fallback content works
Put default text or markup inside a placeholder to show it when no matching child content is supplied:
<h2>
<ng-content select="[card-title]">Untitled card</ng-content>
</h2>
Use fallback content when an empty slot should have a sensible default. It does not make projection conditional: Angular processes placeholders at build time and creates the projected DOM even if a placeholder is hidden. Do not wrap <ng-content> in @if, @for, or @switch to try to control whether projected content is created. For content that must be rendered conditionally, use Angular’s template-fragments guidance.
What component authors should know about ownership
Projected nodes remain part of the parent component’s view, not the receiving component’s own view. The parent’s change detection checks them, and their dependencies resolve from the injector where they were declared—not from the receiving component’s viewProviders. Setting the receiver to OnPush does not make projected nodes part of its view.
Take particular care when projecting children into library components that manage their content. Menus, tabs, and lists may use content queries to configure behavior such as keyboard navigation, focus management, or accessibility attributes. Adding an extra wrapper can break those assumptions even if a query appears to find the items. Follow the component library’s guidance for its child structure.
How to project content into a dynamically created component
Ordinary projection passes static parent markup to a child component. For a component created dynamically with NgComponentOutlet, Angular’s programmatic-rendering guide describes ngComponentOutletContent as the way to provide projected content. Its example builds an array of projection slots from template fragments; use that separate pattern when creating the component dynamically. See Programmatically rendering components.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




