Angular v18 ha recentemente introdotto una nuova funzionalità per definire facilmente un contenuto di fallback per gli elementi ng-content
.
Prima di analizzarla insieme, esploreremo inoltre come in Angular v17 o versioni precedenti fosse possibile ottenere lo stesso risultato.
Nella creazione di componenti UI flessibili e riutilizzabili, la content projection rappresenta uno strumento fondamentale a nostra disposizione. È un pattern grazie a cui possiamo inserire, o proiettare, il contenuto che desideriamo utilizzare all’interno di un altro componente.
Proprio in questo contesto, definire un contenuto di fallback può essere utile per garantire che questo venga visualizzato se non viene fornito alcun contenuto da proiettare.
Definire un contenuto di fallback negli elementi ng-content
Nelle versioni precedenti ad Angular v18, non esisteva una funzionalità specifica per configurare i contenuti di fallback per ng-content
. Tuttavia, ciò non significa che non esistesse una soluzione alternativa.
Diamo un’occhiata a una delle potenziali strategie di implementazione:
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)
L’idea alla base è quella di racchiudere un ng-content
all’interno di un elemento, e utilizzare un viewChild
per determinare se è presente contenuto proiettato o meno.
Al quel punto, il contenuto di fallback può essere gestito utilizzando @if, direttamente fornita dal nuovo control flow, o la direttiva ngIf.
Nota: per versioni precedenti di Angular potrebbe essere necessario un piccolo refactor, ma spero che il concetto sia chiaro. In caso contrario, non esitate a contattarmi 🫶🏻
Angular v18: fallback content per ng-content
A partire da Angular v18, implementare un contenuto di fallback negli elementi ng-content
è estremamente più semplice.
Non dobbiamo far altro che inserire il contenuto di fallback all’interno del tag ng-content
:
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)
Come possiamo vedere, questa nuova funzionalità consente di definire facilmente un contenuto di fallback dedicato per ciascun elemento ng-content
nei componenti.
Quindi, nel caso del seguente esempio:
<my-component>
<footer> New footer </footer>
</my-component>
Code language: HTML, XML (xml)
Il template che verrà generato sarà il seguente:
Default header
Default main content
<footer> New footer </footer>
Code language: HTML, XML (xml)
Nota: nelle versioni precedenti ad Angular v18, questo esempio solleva un errore ❌
Un limite delle strategie appena viste
È importante sottolineare che entrambe le strategie condividono lo stesso limite: in Angular la content projection viene elaborata durante la creazione del componente.
Ciò significa che se si esegue il rendering del contenuto proiettato in modo condizionale, ad esempio utilizzando una condizione @if
o la direttiva ngIf
, il contenuto di fallback non verrà visualizzato, anche se la condizione associata è false
.
Questo limite può essere facilmente superato, con soluzioni diverse in base al caso d’uso specifico che potremmo avere, ma è importante tenerlo a mente quando utilizziamo queste strategie.
Grazie per aver letto questo articolo 🙏
Mi piacerebbe avere qualche feedback quindi grazie in anticipo per qualsiasi commento. 👏
Infine, se ti è piaciuto davvero tanto, condividilo con la tua community. 👋😁