Angular 5 Scroll to top on every Route click

后端 未结 18 1839
遇见更好的自我
遇见更好的自我 2020-11-29 17:49

I am using angular 5. I have a dashboard where I have few sections with small content and few sections with so large content that I am facing a problem when changing router

相关标签:
18条回答
  • 2020-11-29 18:11

    In my case I just added

    window.scroll(0,0);
    

    in ngOnInit() and its working fine.

    0 讨论(0)
  • 2020-11-29 18:11

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

    0 讨论(0)
  • 2020-11-29 18:12

    Although @Vega provides the direct answer to your question, there are issues. It breaks the browser's back/forward button. If you're user clicks the browser back or forward button, they lose their place and gets scrolled way at the top. This can be a bit of a pain for your users if they had to scroll way down to get to a link and decided to click back only to find the scrollbar had been reset to the top.

    Here's my solution to the problem.

    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;
          }
        });
      }
    }
    
    0 讨论(0)
  • 2020-11-29 18:16

    just add

    window.scrollTo({ top: 0);

    to ngOnInit()

    0 讨论(0)
  • 2020-11-29 18:17

    Angular 6.1 and later:

    You can use built in solution available in Angular 6.1+ with option scrollPositionRestoration: 'enabled' to achieve the same.

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

    Angular 6.0 and earlier:

    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);
                }
            });
        }
    }
    

    Note: The expected behavior is that when you navigate back to the page, it should remain scrolled down to the same location it was when you clicked on the link, but scrolling to the top when arriving at every page.

    0 讨论(0)
  • 2020-11-29 18:18

    There are some solutions, make sure to check them all :)


    The router outlet will emit the activate event any time a new component is being instantiated, so we could use (activate) to scroll (for example) to the top:

    app.component.html

    <router-outlet (activate)="onActivate($event)" ></router-outlet>
    

    app.component.ts

    onActivate(event) {
        window.scroll(0,0);
        //or document.body.scrollTop = 0;
        //or document.querySelector('body').scrollTo(0,0)
        ...
    }
    

    Use, for exemple, this solution for a smooth scroll:

        onActivate(event) {
            let scrollToTop = window.setInterval(() => {
                let pos = window.pageYOffset;
                if (pos > 0) {
                    window.scrollTo(0, pos - 20); // how far to scroll on each step
                } else {
                    window.clearInterval(scrollToTop);
                }
            }, 16);
        }
    

    If you wish to be selective, say not every component should trigger the scrolling, you can check it in an if statement like this:

    onActivate(e) {
        if (e.constructor.name)==="login"{ // for example
                window.scroll(0,0);
        }
    }
    

    Since Angular6.1, we can also use { scrollPositionRestoration: 'enabled' } on eagerly loaded modules and it will be applied to all routes:

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

    It will also do the smooth scrolling, already. However this has the inconvenient for doing it on every routing.


    An other solution is to do the top scrolling on router animation. Add this in every transition where you want to scroll to the top:

    query(':enter, :leave', style({ position: 'fixed' }), { optional: true }) 
    
    0 讨论(0)
提交回复
热议问题