• Skip to primary navigation
  • Skip to main content
  • Skip to footer

Codemotion Magazine

We code the future. Together

  • Discover
    • Events
    • Community
    • Partners
    • Become a partner
    • Hackathons
  • Magazine
    • Backend
    • Frontend
    • AI/ML
    • DevOps
    • Dev Life
    • Soft Skills
    • Infographics
  • Talent
    • Discover Talent
    • Jobs
    • Manifesto
  • Companies
  • For Business
    • EN
    • IT
    • ES
  • Sign in
ads

Davide PassafaroMay 13, 2024

Angular fallback content in ng-content

Web Developer
Angular v18 fallback
facebooktwitterlinkedinreddit

Angular v18 recently introduced a new feature to easily define a fallback content in ng-content elements. In this article, I will discuss about it.

However, before diving into it, I will also explore how it was already possible to achieve the same result in Angular v17 or earlier versions.

Recommended article
February 6, 2025

Top Programming Languages in 2025

Lucilla Tomassi

Lucilla Tomassi

Languages and frameworks

When building flexible and reusable UI components, content projection stands as a fundamental tool at your disposal. It is a pattern in which you insert, or project, the content you want to use inside another component.

When configuring a component, defining a fallback content can be useful to ensure something is displayed if no content is provided.

Define fallback content in ng-content elements

Up until Angular v18, there was not a built-in support to fallback content for ng-content. However, this didn’t imply there was no workaround.

Let’s take a look at one of the potential implementation strategies:

import { Component, ElementRef, computed, viewChild } from '@angular/core';

@Component({
  standalone: true,
  selector: 'my-component',
  template: `
    @if(!hasContent()){
      <div> Default content </div>
    }

    <div #wrapper>
      <ng-content></ng-content>
    </div>
  `,
})
export class MyComponent {
  wrapper = viewChild.required<ElementRef<HTMLDivElement>>('wrapper');

  hasContent = computed(
    () => this.wrapper().nativeElement.innerHTML.length > 0
  );
}
Code language: TypeScript (typescript)

The idea behind it is to wrap the ng-content within an element, and utilize the viewChild API to determine whether there is projected content or not.

Then, based on that, the fallback content is displayed using the @if API provided by the new control flow, or the ngIf directive.

Note: in older versions of Angular you may need to refactor this a bit, but I hope the concept of this strategy is clear. If not please feel free to contact me 🫶🏻


Angular v18: fallback content in ng-content

Starting from Angular v18, implementing a fallback content in ng-content elements is extremely easier.

You just need to put the fallback content inside the ng-content tag:

import { Component } from '@angular/core';

@Component({
  standalone: true,
  selector: 'my-component',
  template: `
    <ng-content select="header"> Default header </ng-content>

    <ng-content> Default main content </ng-content>

    <ng-content select="footer"> Default footer </ng-content>
  `,
})
export class MyComponent {}
Code language: TypeScript (typescript)

As you can see, this new feature allows you to easily define a dedicated fallback content for each ng-content element in your component.

So, considering the following example:

<my-component>
  <footer> New footer </footer>
</my-component>
Code language: HTML, XML (xml)

The resulting template will be:

Default header

Default main content

<footer> New footer </footer>
Code language: HTML, XML (xml)

Note: before Angular v18, this would result in an error being thrown ❌

TLDR: is this a good summary? 🤭

Fallback content strategies limitations

It is important to highlight that both strategies share the same limitation: Angular content projection is evaluated on component creation.

This means that if you render the projected content conditionally, for example using an @if condition or the ngIf directive, the fallback content will not be displayed, even if the associated condition is set to false.

This limitation can be easily overcome, with different solutions depending on the specific use case you might have, but it’s important to remember about it when implementing the strategies I’ve presented.


Thanks for reading so far 🙏

I’d like to have your feedback so please feel free to contact me for any. 👏

Then, if you really liked it, share it among your community, tech bros and whoever you want. 👋😁

Related Posts

Native CSS: A Whole New Story – Part 1

Daniele Carta
March 3, 2025
Flock. Fork flutter

Meet Flock: The Flutter Fork Aiming to Accelerate Development

Codemotion
November 4, 2024
setup project, web development, framework, typescript cypress

How to Set Up a Cypress TypeScript Project

Antonello Zanini
September 12, 2023
ViteJS, javascript framework, what is it.

The Rise of ViteJS: Unraveling its Popularity

Codemotion
August 9, 2023
Share on:facebooktwitterlinkedinreddit
Davide Passafaro
My name is Davide Passafaro and I am Senior Frontend Engineer at Awork. I lead two developer communities in Rome, GDG Roma Città and Angular Rome, and actively contribute to the tech community as a writer and speaker. When i shut down my computer I like to play board games and archery, not both together till now. I also like escape rooms and memes.
Don’t Get Yourself Replaced: Top 8 Emerging AI Jobs
Previous Post
ChatGPT 4o: A Comprehensive Overview for Developers
Next Post

Footer

Discover

  • Events
  • Community
  • Partners
  • Become a partner
  • Hackathons

Magazine

  • Tech articles

Talent

  • Discover talent
  • Jobs

Companies

  • Discover companies

For Business

  • Codemotion for companies

About

  • About us
  • Become a contributor
  • Work with us
  • Contact us

Follow Us

© Copyright Codemotion srl Via Marsala, 29/H, 00185 Roma P.IVA 12392791005 | Privacy policy | Terms and conditions