web-dev-qa-db-fra.com

Angular 5 Faites défiler l'écran vers le haut pour chaque clic d'itinéraire.

J'utilise angular 5. J'ai un tableau de bord contenant quelques sections avec un contenu réduit et quelques sections avec un contenu si volumineux que je suis confronté à un problème lorsque je change de routeur en haut. Chaque fois que je dois faire défiler pour aller en haut. Quelqu'un peut-il m'aider à résoudre ce problème afin que, lorsque je change de routeur, ma vue reste toujours en haut.

Merci d'avance.

52
raihan

Si vous rencontrez ce problème dans Angular 6, vous pouvez le résoudre en ajoutant le paramètre scrollPositionRestoration: 'enabled' au module Router de app-routing.module.ts:

@NgModule({
  imports: [RouterModule.forRoot(routes,{
    scrollPositionRestoration: 'enabled'
  })],
  exports: [RouterModule]
})
31
Nimezzz

EDIT: Pour Angular 6+, veuillez utiliser la réponse de Nimesh Nishara Indimagedara en mentionnant:

RouterModule.forRoot(routes, {
    scrollPositionRestoration: 'enabled'
});

Réponse originale:

Si tout échoue, créez un élément HTML vide (par exemple, div) en haut (ou faites défiler jusqu'à l'emplacement souhaité) avec id = "top" sur le modèle (ou le modèle parent):

<div id="top"></div>

Et en composant:

  ngAfterViewInit() {
    // Hack: Scrolls to top of Page after page view initialized
    let top = document.getElementById('top');
    if (top !== null) {
      top.scrollIntoView();
      top = null;
    }
  }
15
GeoRover

Maintenant, il existe une solution intégrée disponible dans Angular 6.1 avec l'option scrollPositionRestoration.

Voir ma réponse sur Défilement angulaire 2 sur Changement d'itinéraire.

14
Abdul Rafay

Bien que @Vega fournisse la réponse directe à votre question, il existe des problèmes. Il casse le bouton Précédent/Suivant du navigateur. Si vous êtes un utilisateur clique sur le bouton précédent ou suivant du navigateur, il perd sa place et se fait défiler en haut. Cela peut être un peu pénible pour vos utilisateurs s’ils doivent faire défiler la page pour accéder à un lien et décider de cliquer à nouveau uniquement pour trouver que la barre de défilement a été réinitialisée.

Voici ma solution au problème.

export class AppComponent implements OnInit {
  isPopState = false;

  constructor(private router: Router, private locStrat: LocationStrategy) { }

  ngOnInit(): void {
    this.locStrat.onPopState(() => {
      this.isPopState = true;
    });

    this.router.events.subscribe(event => {
      // Scroll to top if accessing a page, not via browser history stack
      if (event instanceof NavigationEnd && !this.isPopState) {
        window.scrollTo(0, 0);
        this.isPopState = false;
      }

      // Ensures that isPopState is reset
      if (event instanceof NavigationEnd) {
        this.isPopState = false;
      }
    });
  }
}
5
Sal_Vader_808

Dans mon cas je viens d'ajouter

window.scroll(0,0);

dans ngOnInit() et son bon fonctionnement.

2
Zohab Ali

essaye ça

@NgModule({
  imports: [RouterModule.forRoot(routes,{
    scrollPositionRestoration: 'top'
  })],
  exports: [RouterModule]
})

ce code est supporté angular 6 <=

1
Rokive

Essaye ça:

app.component.ts

import {Component, OnInit, OnDestroy} from '@angular/core';
import {Router, NavigationEnd} from '@angular/router';
import {filter} from 'rxjs/operators';
import {Subscription} from 'rxjs';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.scss'],
})
export class AppComponent implements OnInit, OnDestroy {
    subscription: Subscription;

    constructor(private router: Router) {
    }

    ngOnInit() {
        this.subscription = this.router.events.pipe(
            filter(event => event instanceof NavigationEnd)
        ).subscribe(() => window.scrollTo(0, 0));
    }

    ngOnDestroy() {
        this.subscription.unsubscribe();
    }
}
1
Eray T

Composant: Abonnez-vous à tous les événements de routage au lieu de créer une action dans le modèle et de faire défiler NavigationEnd b/c, sinon vous activez cette option pour les réseaux de navigation défectueux ou les itinéraires bloqués, etc. C'est un moyen sûr de savoir si un itinéraire est navigué avec succès, puis faites défiler. Sinon, ne faites rien.

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit, OnDestroy {

  router$: Subscription;

  constructor(private router: Router) {}

  ngOnInit() {
    this.router$ = this.router.events.subscribe(next => this.onRouteUpdated(next));
  }

  ngOnDestroy() {
    if (this.router$ != null) {
      this.router$.unsubscribe();
    }
  }

  private onRouteUpdated(event: any): void {
    if (event instanceof NavigationEnd) {
      this.smoothScrollTop();
    }
  }

  private smoothScrollTop(): void {
    const scrollToTop = window.setInterval(() => {
      const pos: number = window.pageYOffset;
      if (pos > 0) {
          window.scrollTo(0, pos - 20); // how far to scroll on each step
      } else {
          window.clearInterval(scrollToTop);
      }
    }, 16);
  }

}

HTML

<router-outlet></router-outlet>

Il vous suffit de créer une fonction contenant le réglage du défilement de votre écran

par exemple

window.scroll(0,0) OR window.scrollTo() by passing appropriate parameter.

window.scrollTo (xpos, ypos) -> paramètre attendu.

1
Vijay Barot

Voici une solution qui fait défiler uniquement le haut du composant si la première visite de CHAQUE composant est effectuée (au cas où vous auriez besoin de faire quelque chose de différent par composant):

Dans chaque composant:

export class MyComponent implements OnInit {

firstLoad: boolean = true;

...

ngOnInit() {

  if(this.firstLoad) {
    window.scroll(0,0);
    this.firstLoad = false;
  }
  ...
}
1
0_tr0jan_0

Je continue de chercher une solution intégrée à ce problème, comme dans AngularJS. Mais jusque-là, cette solution fonctionne pour moi, c’est simple, et préserve la fonctionnalité du bouton Précédent.

app.component.html

<router-outlet (deactivate)="onDeactivate()"></router-outlet>

app.component.ts

onDeactivate() {
  document.body.scrollTop = 0;
  // Alternatively, you can scroll to top by using this other call:
  // window.scrollTo(0, 0)
}

Réponse de zurfyxpost original

1
Jared Whipple
export class AppComponent {
  constructor(private router: Router) {
    router.events.subscribe((val) => {
      if (val instanceof NavigationEnd) {
        window.scrollTo(0, 0);
      }
    });
  }

}
1
irhetoric