DEV Community

Cover image for Angular fallback content in ng-content
Davide Passafaro
Davide Passafaro

Posted on

Angular fallback content in ng-content

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.


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
  );
}
Enter fullscreen mode Exit fullscreen mode

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 {}
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

The resulting template will be:

Default header

Default main content

<footer> New footer </footer>
Enter fullscreen mode Exit fullscreen mode

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 leave a comment, like or follow. 👏

Then, if you really liked it, share it among your community, tech bros and whoever you want. And don’t forget to follow me on LinkedIn. 👋😁

Top comments (2)

Collapse
 
jangelodev profile image
João Angelo • Edited

Hi Davide Passafaro,
Your tips are very useful
Thanks for sharing

Collapse
 
davidepassafaro profile image
Davide Passafaro

Thank you 🙏