Angular 6.1 e posterior :
O Angular 6.1 (lançado em 25/07/2018) adicionou suporte interno para lidar com esse problema, por meio de um recurso chamado "Restauração da posição de rolagem do roteador". Conforme descrito no blog oficial do Angular , você só precisa habilitá-lo na configuração do roteador da seguinte maneira:
RouterModule.forRoot(routes, {scrollPositionRestoration: 'enabled'})
Além disso, o blog afirma "Espera-se que isso se torne o padrão em uma futura versão principal". Até o momento, isso não aconteceu (a partir do Angular 8.2), mas, eventualmente, você não precisará fazer nada no seu código, e isso funcionará corretamente imediatamente.
Você pode ver mais detalhes sobre esse recurso e como personalizar esse comportamento nos documentos oficiais .
Angular 6.0 e anterior :
Enquanto a excelente resposta do @ GuilhermeMeireles corrige o problema original, ele apresenta um novo, quebrando o comportamento normal que você espera ao navegar para trás ou para frente (com os botões do navegador ou via Localização no código). O comportamento esperado é que, quando você voltar para a página, ele permanecerá rolado para baixo no mesmo local em que você clicou no link, mas a rolagem para o topo ao chegar a todas as páginas obviamente quebra essa expectativa.
O código abaixo expande a lógica para detectar esse tipo de navegação, assinando a sequência PopStateEvent do Location e pulando a lógica de rolagem para o topo se a página recém-chegada é resultado de um evento desse tipo.
Se a página da qual você navega for longa o suficiente para cobrir toda a janela de exibição, a posição de rolagem será restaurada automaticamente, mas como @JordanNelson apontou corretamente, se a página for mais curta, será necessário acompanhar a posição de rolagem y original e restaurá-la explicitamente quando você voltar para a página. A versão atualizada do código também abrange esse caso, sempre restaurando explicitamente a posição de rolagem.
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' })