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.

Les animations d'entrée et de sortie dans Angular

Note

Si vous ne connaissez pas les animations dans Angular, il est recommandé d'abord de lire la page La base des animations.

Les animations d'entrée et de sortie sont essentielles pour créer une expérience utilisateur fluide et professionnelle. Nous allons voir comment les mettre en place à travers un exemple concret : un système de notifications toast.

CONCEPT CLÉ

Les animations d'entrée (:enter) et de sortie (:leave) permettent de contrôler comment les éléments apparaissent et disparaissent de notre interface.

Avant tout: mise en place des animations

Si vous n'avez pas encore installé Angular Animations, vous pouvez le faire avec la commande suivante (vous pouvez le vérifier dans le fichier package.json)

bash
ng add @angular/animations

Ensuite, allez dans le fichier app.config.ts et ajoutez dans la liste des providers:

ts
import { AppComponent } from './app/app.component';
import { bootstrapApplication } from '@angular/platform-browser';
import { provideAnimationsAsync } from '@angular/platform-browser/animations';

bootstrapApplication(AppComponent, {
    providers: [
        provideAnimationsAsync()
    ]
});

Charger les animations dès le chargement de l'application

Si vous avez besoin d'animations dès le chargement de votre application, vous devrez utiliser le module d'animations chargé immédiatement plutôt que de manière asynchrone. Pour cela, importez provideAnimations depuis @angular/platform-browser/animations et utilisez-le à la place de provideAnimationsAsync :

Implémentation du système de toast

Commençons par créer notre système de notifications toast :

ts
import { Component, input, inject } from '@angular/core';
import { animate, style, transition, trigger } from '@angular/animations';
import { ToastService } from './toast.service';

@Component({
  selector: 'app-toast',
  standalone: true,
  template: `
   @if (toastService.showToast()) {
    <div class="toast" @toastAnimation>
      {{ toastService.message() }}
    </div>
   }
  `,
  styles: `
    .toast {
      position: fixed;
      right: 20px;
      top: 20px;
      padding: 1rem;
      background: #333;
      color: white;
      border-radius: 4px;
    }
  `,
  animations: [
    trigger('toastAnimation', [
      transition(':enter', [
        style({ transform: 'translateX(100%)', opacity: 0 }),
        animate('150ms ease-out', style({ transform: 'translateX(0)', opacity: 1 }))
      ]),
      transition(':leave', [
        animate('150ms ease-in', style({ transform: 'translateX(100%)', opacity: 0 }))
      ])
    ])
  ]
})
export class ToastComponent {
  toastService = inject(ToastService)
}
ts
import { Injectable, signal } from '@angular/core';

@Injectable({
  providedIn: 'root',
})
export class ToastService {
  showToast = signal(false);
  message = signal('');

  show(msg: string) {
    this.message.set(msg);
    this.showToast.set(true);

    setTimeout(() => {
      this.showToast.set(false);
    }, 3000);
  }
}
ts
import { Component, inject } from '@angular/core';
import { ToastComponent } from './toast.component';
import { ToastService } from './toast.service';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [ToastComponent],
  template: `
    <app-toast />
    <button (click)="toastService.show('Hello World!')">Afficher Toast</button>
  `,
})
export class AppComponent {
  toastService = inject(ToastService);
}

Notez que nous n'avons pas défini state dans notre trigger. C'est parce que nous n'avons pas besoin de définir un état initial et final. Nous pouvons simplement utiliser les transitions :enter et :leave pour gérer l'animation. Donc, dans le template, nous ne mettons pas le binding dynamique [@toastAnimation] sur le div mais juste @toastAnimation.

L'animation d'entrée (:enter)

ts
transition(':enter', [
  // Position initiale : décalé de 100% vers la droite et invisible
  style({ transform: 'translateX(100%)', opacity: 0 }),
  // Animation vers la position finale : centré et visible
  animate('150ms ease-out', style({ transform: 'translateX(0)', opacity: 1 }))
])

Ici, la particularité est que l'animation d'entrée est déclenchée par le changement d'état :enter. C'est un alias pour la transition void => *.

L'animation de sortie (:leave)

ts
transition(':leave', [
  // Animation vers la position finale : sort vers la droite en devenant invisible
  animate('150ms ease-in', style({ transform: 'translateX(100%)', opacity: 0 }))
])

Ici, l'animation de sortie est déclenchée par le changement d'état :leave. C'est un alias pour la transition * => void.

Note

Les animations :enter et :leave sont des alias pour les transitions void => * et * => void donc elles ne fonctionnent que lorsque les éléments sont ajoutés ou supprimés du DOM par Angular (par exemple avec @if ou @for).

IMPORTANT

Les comportements d'entrée/sortie peuvent parfois être déroutants. En règle générale, considérez que tout élément ajouté au DOM par Angular passe par la transition :enter. Seuls les éléments directement supprimés du DOM par Angular passent par la transition :leave. Par exemple, la vue d'un élément est supprimée du DOM parce que son parent est en train d'être supprimé 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 !