Angular 2 Scroll to top on Route Change : pourquoi c’est important et comment l’implémenter
\n\nImaginez que vous parcourez une longue page de documentation, que vous arrivez au milieu, que vous cliquez sur un lien — et vous vous retrouvez en bas d’une nouvelle section. Familier ? C’est exactement ce problème que résout la mécanique Angular 2 scroll to top on route change. Sans elle, l’expérience utilisateur en pâtit : il faut remonter manuellement avec la molette de la souris ou appuyer sur Home, ce qui est agaçant et augmente le taux de rebond.
\n\nDans cet article, nous allons voir comment faire en sorte qu’Angular fasse défiler automatiquement la page vers le haut à chaque transition entre les routes. Vous découvrirez non seulement une solution prête à l’emploi, mais aussi pourquoi cela fonctionne ainsi. L’article est écrit pour les débutants, mais sera également utile aux développeurs expérimentés souhaitant rafraîchir leurs connaissances.
\n\nPourquoi Angular ne le fait-il pas "par défaut" ?
\n\nAngular est un puissant framework SPA, mais son comportement lors de la navigation peut surprendre. Par défaut, lors d’un changement de route, le navigateur ne réinitialise pas la position de défilement. Pourquoi ? Parce que le Router Angular considère la transition comme un remplacement de composant dans <router-outlet>, et non comme le chargement d’une nouvelle page. Le navigateur, lui, pense : « Je suis toujours sur le même document, pourquoi devrais-je défiler ? ».
Cela est particulièrement visible si vous avez de longues listes, des tableaux ou de la documentation. L’utilisateur clique sur un lien en bas de page — et le nouveau contenu s’affiche, mais le défilement reste en bas. La solution à ce problème est d’indiquer explicitement à Angular : « Hé, à chaque transition, remonte en haut ! ».
\n\nDeux approches pour résoudre le problème
\n\nIl existe deux méthodes principales pour implémenter le scroll to top on route change dans Angular 2+ :
\n\n- \n
- Un gestionnaire global dans AppComponent — simple, mais ne fonctionne pas toujours correctement avec les routes imbriquées. \n
- L’utilisation de la configuration des routes — plus flexible, permet de personnaliser le comportement pour chaque route individuellement. \n
Nous allons examiner les deux, mais je recommande de vous arrêter sur la seconde — elle offre plus de contrôle.
\n\nMéthode 1 : Un gestionnaire global simple (pour un démarrage rapide)
\n\nOuvrez votre fichier app.component.ts (ou le composant racine) et ajoutez un abonnement aux événements du Router. Code en TypeScript :
\nimport { Component, OnInit } from '@angular/core';\nimport { Router, NavigationEnd } from '@angular/router';\nimport { filter } from 'rxjs/operators';\n\n@Component({\n selector: 'app-root',\n templateUrl: './app.component.html',\n styleUrls: ['./app.component.css']\n})\nexport class AppComponent implements OnInit {\n constructor(private router: Router) {}\n\n ngOnInit() {\n this.router.events.pipe(\n filter(event => event instanceof NavigationEnd)\n ).subscribe(() => {\n window.scrollTo(0, 0);\n });\n }\n}\n\n\nIci, nous nous abonnons aux événements du routeur, filtrons uniquement NavigationEnd (le moment où la transition est terminée), et appelons window.scrollTo(0, 0). Simple, mais il y a un inconvénient : si vous avez des routes imbriquées (par exemple, des routes enfants dans un composant), ce code peut se déclencher trop tôt ou ne pas se déclencher du tout.
Méthode 2 : La solution correcte avec la configuration des routes (recommandée)
\n\nCette approche utilise l’option intégrée scrollPositionRestoration dans le Router Angular. Depuis Angular 6.1, il est possible de configurer la restauration/réinitialisation automatique du défilement directement dans la configuration du routage.
Ouvrez votre fichier app-routing.module.ts et ajoutez l’option scrollPositionRestoration: 'top' dans RouterModule.forRoot() :
\nimport { NgModule } from '@angular/core';\nimport { RouterModule, Routes } from '@angular/router';\n\nconst routes: Routes = [\n { path: '', component: HomeComponent },\n { path: 'about', component: AboutComponent },\n { path: 'contact', component: ContactComponent }\n];\n\n@NgMod