Angular est-il vraiment plus compliqué que React ?

Quand on débute avec Angular, il est facile de se sentir découragé face à la multitude de concepts à assimiler. Cette complexité peut inciter à se tourner vers des frameworks comme React, qui semblent plus simples à première vue. Mais est-ce vraiment le cas ?

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

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