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.

afterRender : Le hook de cycle de vie pour manipuler le DOM après le rendu

WARNING

afterRender est disponible depuis Angular 17.

Le hook afterRender est une nouveauté d'Angular qui permet d'exécuter du code une fois que le DOM a été complètement rendu. C'est particulièrement utile lorsque vous avez besoin d'accéder ou de manipuler des éléments du DOM après leur création.

DIFFÉRENCES CLÉS

  • afterNextRender : s'exécute une seule fois après le prochain cycle de rendu
  • afterRender : s'exécute après chaque cycle de rendu

Comprendre afterRender avec un exemple concret

Imaginez que vous êtes dans une bibliothèque où vous devez aligner tous les livres d'une étagère pour qu'ils aient la même hauteur visuelle, mais vous ne pouvez le faire qu'une fois que tous les livres sont placés sur l'étagère. C'est exactement ce que fait afterRender : il attend que tous les éléments soient "placés" dans le DOM avant d'effectuer des opérations sur eux.

Utilisation pratique

Dans notre exemple, nous avons une liste d'utilisateurs affichée sous forme de cartes. Nous voulons que toutes les cartes aient la même hauteur pour un affichage harmonieux, mais nous ne pouvons calculer cette hauteur qu'après que toutes les cartes sont rendues dans le DOM.

CONSEIL

Utilisez afterRender quand vous avez besoin de :

  • Mesurer des dimensions d'éléments
  • Initialiser des bibliothèques tierces qui nécessitent que le DOM soit prêt
  • Effectuer des animations après le rendu initial

ATTENTION

afterRender s'exécute après CHAQUE cycle de rendu. Assurez-vous que vos opérations sont optimisées pour éviter les problèmes de performance.

Voici un exemple qui montre les points clés de l'utilisation d'afterRender :

ts
import { Component, afterRender, ElementRef, QueryList, ViewChildren } from '@angular/core';

interface User {
  id: number;
  name: string;
}

@Component({
  selector: 'app-user-list',
  standalone: true,
  template: `
    <div class="user-container">
      @for (user of users; track user.id) {
        <div class="user-card" #userCard>
          {{ user.name }}
        </div>
      }
    </div>
    <button (click)="addUser()">Add user</button>
  `
})
export class UserListComponent {
  @ViewChildren('userCard') userCards!: QueryList<ElementRef<HTMLDivElement>>;
  users: User[] = [
    {
      id: 1,
      name: 'John Doe',
    },
    {
      id: 2,
      name: 'Jane Doe',
    },
    {
      id: 3,
      name: 'John Smith',
    },
  ];

  constructor() {
    afterRender(() => {
      this.updateCardHeights();
    });
  }

  private updateCardHeights() {
    // Récupérer tous les éléments avec la classe user-card
    const cards = this.userCards.toArray().map(card => card.nativeElement);
    
    // Réinitialiser les hauteurs pour un nouveau calcul
    cards.forEach(card => {
      (card as HTMLElement).style.height = 'auto';
    });

    // Trouver la hauteur maximale selon la taille d'écran
    let maxHeight = 0;
    if (window.innerWidth >= 768) { // Pour les écrans >= tablette
      cards.forEach(card => {
        const height = card.getBoundingClientRect().height + 30;
        maxHeight = Math.max(maxHeight, height);
      });

      // Appliquer la même hauteur à toutes les cartes
      cards.forEach(card => {
        (card as HTMLElement).style.height = `${maxHeight}px`;
      });
    }
    // Sur mobile, on laisse la hauteur automatique pour plus de flexibilité
  }

  addUser() {
    const nbUsers = this.users.length;
    this.users.push({
      id: nbUsers + 1,
      name: `User ${nbUsers + 1}`,
    });
  }
}

Dans cet exemple, les points importants sont :

  1. L'importation de afterRender depuis @angular/core
  2. L'utilisation dans le constructeur pour s'assurer que le code s'exécute après chaque rendu
  3. L'accès aux éléments du DOM via ViewChildren pour manipuler les hauteurs

BONNE PRATIQUE

Pour de meilleures performances, vous pouvez conditionner l'exécution du code dans afterRender :

ts
afterRender(() => {
  if (this.shouldUpdateHeights) {
    this.updateCardHeights();
    this.shouldUpdateHeights = false;
  }
});

Différence avec ngAfterViewInit

IMPORTANT

Contrairement à ngAfterViewInit qui ne s'exécute qu'une seule fois après l'initialisation de la vue, afterRender s'exécute après chaque cycle de rendu, ce qui le rend plus adapté pour les mises à jour dynamiques du DOM.

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