Les nouveautés d'Angular 19 en 4 minutes

Angular 19 vient de sortir, et il y a beaucoup de nouveautés intéressantes : hydratation incrémentale, linkedSignal, l'API des ressources, et plein d'autres choses. Venez découvrir tout ça en moins de 4 minutes !

Abonnez-vous à notre chaîne

Pour profiter des prochaines vidéos sur Angular, abonnez-vous à la nouvelle chaîne YouTube !

Skip to content

Vous souhaitez recevoir de l'aide sur ce sujet ? rejoignez la communauté Angular.fr sur Discord.

Maîtriser la projection de contenu avec ng-content dans Angular

La projection de contenu est un concept essentiel dans Angular qui permet de créer des composants vraiment réutilisables. Imaginez un cadre photo : le cadre reste le même, mais vous pouvez y mettre différentes photos. C'est exactement ce que fait ng-content !

Comprendre ng-content avec un exemple concret

Prenons l'exemple d'une carte utilisateur réutilisable. Nous voulons créer un composant qui peut afficher différentes informations sur un utilisateur tout en gardant le même style.

CONSEIL

La projection de contenu est particulièrement utile pour créer des composants d'interface utilisateur réutilisables comme des cartes, des modales ou des panneaux.

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

@Component({
  selector: 'app-simple-card',
  standalone: true,
  template: `
    <div class="simple-card">
      <ng-content />
    </div>
  `,
  styles: `
    .simple-card {
      padding: 16px;
      border: 1px solid #ccc;
      border-radius: 4px;
      margin: 8px;
    }
  `
})
export class SimpleCardComponent {}
ts
import { Component } from '@angular/core';
import { SimpleCardComponent } from './simple-card.component';

@Component({
  selector: 'app-home',
  standalone: true,
  imports: [SimpleCardComponent],
  template: `
    <app-simple-card>
      <h2>{{ user.name }}</h2>
      <p>{{ user.email }}</p>
    </app-simple-card>
  `
})
export class HomeComponent {
  user: any = {
    id: 1,
    name: 'John Doe',
    username: 'johndoe',
    email: '[email protected]'
  };
}

Dans cet exemple simple, tout le contenu placé entre les balises <app-simple-card> sera projeté à l'endroit où se trouve le <ng-content> dans le composant SimpleCardComponent.

CONSEIL

Le contenu projeté peut être n'importe quel élément HTML, y compris d'autres composants. Et pas besoin d'importer <ng-content> dans votre composant. Utilisez simplement <ng-content> dans votre template.

Utilisation avancée avec les sélecteurs

Voici comment implémenter cette carte utilisateur :

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

@Component({
  selector: 'app-user-card',
  standalone: true,
  template: `
    <div class="card">
      <div class="card-header">
        <ng-content select="[header]"></ng-content>
      </div>
      <div class="card-body">
        <ng-content />
      </div>
      <div class="card-footer">
        <ng-content select="[footer]"></ng-content>
      </div>
    </div>
  `,
  styles: `
    .card {
      border: 1px solid #ddd;
      border-radius: 8px;
      padding: 16px;
    }
  `
})
export class UserCardComponent {}
ts
import { Component } from '@angular/core';
import { UserCardComponent } from './user-card.component';

@Component({
  selector: 'app-home',
  standalone: true,
  imports: [UserCardComponent],
  template: `
    <app-user-card>
      <div header>
        <h2>{{ user.name }}</h2>
      </div>
      
      <div>
        <p>Email: {{ user.email }}</p>
        <p>Username: {{ user.username }}</p>
      </div>

      <div footer>
        <button>Voir le profil</button>
      </div>
    </app-user-card>
  `
})
export class HomeComponent {
  user: any = {
    id: 1,
    name: 'John Doe',
    username: 'johndoe',
    email: '[email protected]'
  };
}

Vous pouvez utiliser différents types de sélecteurs CSS pour cibler précisément le contenu à projeter :

  • Par attribut : select="[header]"
  • Par classe : select=".header"
  • Par élément : select="header"

Lorsque vous utilisez plusieurs ng-content avec des sélecteurs, il est possible d'avoir un ng-content par défaut qui capturera tout le contenu non sélectionné. L'ordre des ng-content dans le template n'a pas d'importance.

Contenu de secours (Fallback Content)

Depuis Angular 18

La possibilité d'afficher un contenu de secours est disponible depuis Angular 18.

Une fonctionnalité très utile de ng-content est la possibilité d'afficher un contenu de secours lorsqu'aucun contenu n'est projeté. C'est particulièrement utile pour fournir des valeurs par défaut.

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

@Component({
  selector: 'app-user-card',
  standalone: true,
  template: `
    <div class="card-header">
      <ng-content select="[header]">
        <h2>Utilisateur Anonyme</h2>
      </ng-content>
    </div>
    <div class="card-body">
      <ng-content select="[body]">
        <p>Aucune information disponible</p>
      </ng-content>
    </div>
  `
})
export class UserCardComponent {}
ts
@Component({
  selector: 'app-home',
  standalone: true,
  imports: [UserCardComponent],
  template: `
    <!-- Cette carte utilisera le contenu de secours -->
    <app-user-card>
    </app-user-card>

    <!-- Cette carte affichera le contenu fourni -->
    <app-user-card>
      <div header>
        <h2>{{ user.name }}</h2>
      </div>
      <div body>
        <p>Email: {{ user.email }}</p>
      </div>
    </app-user-card>
  `
})

ASTUCE

Le contenu de secours est particulièrement utile pour créer des composants qui restent fonctionnels même lorsque certaines parties du contenu ne sont pas fournies. Cela améliore la réutilisabilité et la robustesse de vos composants.

Alias de projection avec ngProjectAs

Angular fournit un attribut spécial ngProjectAs qui permet de spécifier un sélecteur CSS sur n'importe quel élément. Lors de la projection de contenu, Angular utilisera la valeur de ngProjectAs au lieu de l'identité de l'élément pour faire correspondre avec le sélecteur de ng-content.

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

@Component({
  selector: 'app-user-card',
  standalone: true,
  template: `
    <div class="card">
      <ng-content select="[card-title]"></ng-content>
      <div class="card-divider"></div>
      <ng-content></ng-content>
    </div>
  `,
  styles: `
    .card {
      border: 1px solid #ddd;
      padding: 16px;
    }
    .card-divider {
      border-top: 1px solid #eee;
      margin: 8px 0;
    }
  `
})
export class UserCardComponent {}
ts
import { Component } from '@angular/core';
import { UserCardComponent } from './user-card.component';

@Component({
  selector: 'app-home',
  standalone: true,
  imports: [UserCardComponent],
  template: `
    <app-user-card>
      <h2 ngProjectAs="[card-title]">{{ user.name }}</h2>
      <p>Email: {{ user.email }}</p>
    </app-user-card>
  `
})
export class HomeComponent {
  user: User = {
    id: 1,
    name: 'John Doe',
    email: '[email protected]'
  };
}

Dans cet exemple, même si nous utilisons un élément <h2>, l'attribut ngProjectAs="[card-title]" permet de le projeter dans le ng-content qui a le sélecteur select="[card-title]".

IMPORTANT

ngProjectAs ne supporte que les valeurs statiques et ne peut pas être lié à des expressions dynamiques. Par exemple, ceci ne fonctionnera pas :

ts
<h2 [ngProjectAs]="dynamicSelector">Titre</h2>

UTILISATION

Cette fonctionnalité est particulièrement utile lorsque vous voulez projeter un élément HTML spécifique (comme un <h2> ou un <p>) dans un emplacement particulier, sans avoir à l'envelopper dans un conteneur supplémentaire.

Cas d'usage courants de ngProjectAs

Voici des situations courantes où l'utilisation de ngProjectAs est particulièrement pertinente :

ScénarioDescriptionAvantage
Composants de navigationProjection d'éléments <a> comme items de menu sans wrapperGarde la sémantique HTML tout en permettant une projection ciblée
Tableaux de donnéesProjection directe de cellules <td> dans différentes colonnesÉvite d'ajouter des divs supplémentaires qui casseraient la structure du tableau
FormulairesProjection de champs <input> dans différentes sections du formulaireMaintient l'accessibilité native des éléments de formulaire
ListesProjection d'éléments <li> dans différentes sections de listePréserve la structure sémantique des listes
En-têtes de sectionProjection de titres (<h1> à <h6>) dans des emplacements spécifiquesConserve la hiérarchie des titres pour le SEO
Composants de modalProjection de boutons natifs dans différentes zones (header, footer)Garde les avantages des éléments natifs pour l'accessibilité

BONNE PRATIQUE

Utilisez ngProjectAs quand vous voulez préserver la sémantique HTML et l'accessibilité tout en bénéficiant de la flexibilité de la projection de contenu.

Chaque mois, recevez en avant-première notre newsletter avec les dernières actualités, tutoriels, astuces et ressources Angular directement par email !