Découvrez les nouveautés d'Angular 20 en quelques minutes

Angular 20 arrive avec plusieurs nouveautés et stabilisation des API: Zoneless, les APIs resource() et httpResource(), un nouveau runner de tests, etc. La vidéo vous donne un aperçu de ces nouveautés.

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.

Utiliser le Contexte pour propager des données dans Angular

Imaginez que vous ayez besoin de partager des informations entre un composant parent et plusieurs composants enfants. La méthode traditionnelle consisterait à passer ces données via des input() à chaque niveau, ce qui peut devenir fastidieux et difficile à maintenir.

Le Problème

Prenons un exemple concret : un système d'onglets où chaque onglet doit savoir :

  • Quel onglet est actuellement actif
  • Comment changer l'onglet actif

Sans contexte, vous devriez faire quelque chose comme ceci :

ts
@Component({
  template: `
    <app-tabs-container [activeTab]="activeTab" (tabChange)="onTabChange($event)">
      <app-tab [activeTab]="activeTab" (tabChange)="onTabChange($event)" [id]="0">
        Contenu 1
      </app-tab>
      <app-tab [activeTab]="activeTab" (tabChange)="onTabChange($event)" [id]="1">
        Contenu 2
      </app-tab>
    </app-tabs-container>
  `
})

PROBLÈME

Cette approche crée beaucoup de code répétitif et rend la maintenance plus difficile. Chaque composant doit explicitement recevoir et transmettre les mêmes propriétés.

La Solution avec le Contexte

Au lieu de cela, nous pouvons utiliser un contexte pour partager ces informations automatiquement avec tous les composants enfants. Voici comment :

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

export interface TabsContext {
  activeTabId: number;
  selectTab: (id: number) => void;
}

export const TABS_CONTEXT = new InjectionToken<TabsContext>('TABS_CONTEXT');
ts
@Component({
  selector: 'app-tabs-container',
  standalone: true,
  template: `
    <div class="tabs-container">
      <ng-content></ng-content>
    </div>
  `,
  providers: [
    {
      provide: TABS_CONTEXT,
      useExisting: TabsContainerComponent
    }
  ]
})
export class TabsContainerComponent implements TabsContext {
    activeTab = input.required<number>();
    tabChange = output<number>();
}
ts
import { input, inject, Component, computed } from '@angular/core';

@Component({
  selector: 'app-tab',
  standalone: true,
  template: `
    @if (isActive()) {
      <div class="tab-content">
        <ng-content></ng-content>
      </div>
    }
  `
})
export class TabComponent {
    protected tabsContext = inject(TABS_CONTEXT);
    id = input.required<number>();
    isActive = computed(() => this.tabsContext.activeTabId() === this.id());
}

Utilisation

Maintenant, l'utilisation devient beaucoup plus simple et propre :

ts
@Component({
  selector: 'app-user-profile',
  standalone: true,
  imports: [TabsContainerComponent, TabComponent],
  template: `
    <app-tabs-container [activeTab]="activeTab" (tabChange)="onTabChange($event)">
      <app-tab [id]="0">
        <h3>Informations Utilisateur</h3>
        <p>Nom: {{ user.name }}</p>
      </app-tab>
      <app-tab [id]="1">
        <h3>Paramètres</h3>
        <p>Email: {{ user.email }}</p>
      </app-tab>
    </app-tabs-container>
  `
})
```