Angular 6.1 et versions ultérieures :
Angular 6.1 (publié le 25/07/2018) a ajouté une prise en charge intégrée pour gérer ce problème, via une fonctionnalité appelée "Router Scroll Position Restoration". Comme décrit dans le blog officiel Angular , il vous suffit d'activer cela dans la configuration du routeur comme ceci:
RouterModule.forRoot(routes, {scrollPositionRestoration: 'enabled'})
En outre, le blog déclare "Il est prévu que cela deviendra la valeur par défaut dans une future version majeure". Jusqu'à présent, cela ne s'est pas produit (à partir d'Angular 8.2), mais vous n'aurez finalement pas besoin de faire quoi que ce soit dans votre code, et cela fonctionnera correctement hors de la boîte.
Vous pouvez voir plus de détails sur cette fonctionnalité et comment personnaliser ce comportement dans les documents officiels .
Angular 6.0 et versions antérieures :
Alors que l'excellente réponse de @ GuilhermeMeireles corrige le problème d'origine, elle en introduit un nouveau, en brisant le comportement normal que vous attendez lorsque vous naviguez en arrière ou en avant (avec les boutons du navigateur ou via Emplacement dans le code). Le comportement attendu est que lorsque vous revenez à la page, elle doit rester déroulée jusqu'au même emplacement que lorsque vous avez cliqué sur le lien, mais le défilement vers le haut en arrivant à chaque page rompt évidemment cette attente.
Le code ci-dessous développe la logique pour détecter ce type de navigation en s'abonnant à la séquence PopStateEvent de Location et en sautant la logique de défilement vers le haut si la page nouvellement arrivée est le résultat d'un tel événement.
Si la page à partir de laquelle vous revenez est suffisamment longue pour couvrir toute la fenêtre, la position de défilement est restaurée automatiquement, mais comme @JordanNelson l'a correctement souligné, si la page est plus courte, vous devez garder la trace de la position de défilement y d'origine et la restaurer. explicitement lorsque vous revenez à la page. La version mise à jour du code couvre également ce cas, en restaurant toujours explicitement la position de défilement.
import { Component, OnInit } from '@angular/core';
import { Router, NavigationStart, NavigationEnd } from '@angular/router';
import { Location, PopStateEvent } from "@angular/common";
@Component({
selector: 'my-app',
template: '<ng-content></ng-content>',
})
export class MyAppComponent implements OnInit {
private lastPoppedUrl: string;
private yScrollStack: number[] = [];
constructor(private router: Router, private location: Location) { }
ngOnInit() {
this.location.subscribe((ev:PopStateEvent) => {
this.lastPoppedUrl = ev.url;
});
this.router.events.subscribe((ev:any) => {
if (ev instanceof NavigationStart) {
if (ev.url != this.lastPoppedUrl)
this.yScrollStack.push(window.scrollY);
} else if (ev instanceof NavigationEnd) {
if (ev.url == this.lastPoppedUrl) {
this.lastPoppedUrl = undefined;
window.scrollTo(0, this.yScrollStack.pop());
} else
window.scrollTo(0, 0);
}
});
}
}
RouterModule.forRoot(appRoutes, { scrollPositionRestoration: 'enabled' })