Appearance
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 renduafterRender
: 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 :
- L'importation de
afterRender
depuis@angular/core
- L'utilisation dans le constructeur pour s'assurer que le code s'exécute après chaque rendu
- 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.