Building a burger is one of the simplest tasks around. The base stays the same while the filling changes, so let's put together our own burger component.
In this piece, we look at how to use ng-content to create a flexible region and support multiple insertion points.
- Leverage
ng-contentfor content projection. - Use multiple slots for targeted content placement.
Feel free to experiment with the live demo.
The setup.
We have a collection of ingredient components ready to assemble into our burger component.
<top-bun></top-bun>
<cheese></cheese>
<bottom-bun></bottom-bun>
<tomato></tomato>
<onion></onion>
<meat></meat>
The goal is to build a burger component that wraps these ingredients, much like a real burger, using two powerful Angular features: content projection and the ng-content element.
Content projection and ng-content
Angular makes components reusable through content projection. This approach lets you declare a region in a component that can be filled with whatever content you choose, whether that's plain elements or other components.
With this technique, we can define a wrapper while deciding which parts of the UI are fixed and which are flexible.
When you place the ng-content tag in a template, Angular swaps that area out for the elements or components you provide.
To get started, generate the burger component and insert the ng-content tag into its template.
import { Component } from '@angular/core';
@Component({
selector: 'burger',
templateUrl: './burger.component.html',
})
export class BurgerComponent {}
<div class="burger">
<ng-content></ng-content>
</div>
That's step one done. Now move the ingredients into the burger component's body.
<burger>
<top-bun></top-bun>
<cheese></cheese>
<tomato></tomato>
<onion></onion>
<meat></meat>
<bottom-bun></bottom-bun>
</burger>
It works. The burger component now accepts child elements and components inside it, with the burger acting as the wrapper.
Why isn't the meat in the middle?
Multiple slots
Every burger needs the meat at the center. We want to stay flexible, adding components or forcing them into place without breaking the burger, so the burger component should render elements in specific areas.
The ng-content element has an optional selector property. This picks up content that matches a CSS selector, such as a class or attribute, letting us define those areas.
Update the default burger with the following:
- include top-bun and bottom-bun as defaults for all burgers.
- three
ng-contentslots with selectors for top, middle, and bottom. - an
ng-contentslot for the price. - a default
ng-contentfor ingredients without a specific place.
<div class="burger">
<top-bun></top-bun>
<ng-content select="[top]"></ng-content>
<ng-content select="[middle]"></ng-content>
<ng-content select="[bottom]"></ng-content>
<bottom-bun></bottom-bun>
</div>
<div class="price">
<ng-content select="[price]"></ng-content>
</div>
<div>
<p>These ingredients don't have a location</p>
<ng-content></ng-content>
</div>
Now our burger component is ready. Any ingredient or piece without a designated place falls into the other div.
The tomato and onion have no attributes, so they end up in the default ng-content.
<!-- Burger with ingredients without location.-->
<burger>
<tomato></tomato>
<cheese top></cheese>
<meat middle></meat>
<onion></onion>
<span price>4€</span>
</burger>
Wrapping up!
We now have a reusable component built with content projection. It's ready to construct new burgers, with the ability to place elements into specific spots or fall back to a default location.
That's all there is to it! Hopefully, this gives you a helpful start with ng-content and adds more flexibility to your components.
If this helped you, pass it along!
Photo by Haseeb Jamil on Unsplash


