Angular fallback content in ng-content | DevsDay.ru

IT-блоги Angular fallback content in ng-content

dev.to 8 мая 2024 г. Davide Passafaro


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
  );
}

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 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 {}

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>

The resulting template will be:

Default header

Default main content

<footer> New footer </footer>

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’s 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, 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. 👋😁

Источник: dev.to

Наш сайт является информационным посредником. Сообщить о нарушении авторских прав.

angular frontend webdev javascript