Angular 2 Scroll to top on Route Change





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







183















In my Angular 2 app when I scroll down a page and click the link at the bottom of the page, it does change the route and takes me the next page but it doesn't scroll to the top of the page. As a result, if the first page is lengthy and 2nd page has few contents, it gives an impression that the 2nd page lacks the contents. Since the contents are visible only if user scroll to the top of the page.



I can scroll the window to the top of the page in ngInit of the component but, is there any better solution that can automatically handle all routes in my app?










share|improve this question




















  • 1





    Since Angular 6.1 we can use { scrollPositionRestoration: 'enabled' } on eagerly loaded modules or just in app.module and it will be applied to all routes. RouterModule.forRoot(appRoutes, { scrollPositionRestoration: 'enabled' })

    – Manwal
    Mar 16 at 17:22


















183















In my Angular 2 app when I scroll down a page and click the link at the bottom of the page, it does change the route and takes me the next page but it doesn't scroll to the top of the page. As a result, if the first page is lengthy and 2nd page has few contents, it gives an impression that the 2nd page lacks the contents. Since the contents are visible only if user scroll to the top of the page.



I can scroll the window to the top of the page in ngInit of the component but, is there any better solution that can automatically handle all routes in my app?










share|improve this question




















  • 1





    Since Angular 6.1 we can use { scrollPositionRestoration: 'enabled' } on eagerly loaded modules or just in app.module and it will be applied to all routes. RouterModule.forRoot(appRoutes, { scrollPositionRestoration: 'enabled' })

    – Manwal
    Mar 16 at 17:22














183












183








183


48






In my Angular 2 app when I scroll down a page and click the link at the bottom of the page, it does change the route and takes me the next page but it doesn't scroll to the top of the page. As a result, if the first page is lengthy and 2nd page has few contents, it gives an impression that the 2nd page lacks the contents. Since the contents are visible only if user scroll to the top of the page.



I can scroll the window to the top of the page in ngInit of the component but, is there any better solution that can automatically handle all routes in my app?










share|improve this question
















In my Angular 2 app when I scroll down a page and click the link at the bottom of the page, it does change the route and takes me the next page but it doesn't scroll to the top of the page. As a result, if the first page is lengthy and 2nd page has few contents, it gives an impression that the 2nd page lacks the contents. Since the contents are visible only if user scroll to the top of the page.



I can scroll the window to the top of the page in ngInit of the component but, is there any better solution that can automatically handle all routes in my app?







angular angular2-routing angular2-template angular2-directives






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Sep 11 '18 at 5:52









Rohit Sharma

2,23521228




2,23521228










asked Sep 20 '16 at 18:13









Naveed AhmedNaveed Ahmed

3,19782867




3,19782867








  • 1





    Since Angular 6.1 we can use { scrollPositionRestoration: 'enabled' } on eagerly loaded modules or just in app.module and it will be applied to all routes. RouterModule.forRoot(appRoutes, { scrollPositionRestoration: 'enabled' })

    – Manwal
    Mar 16 at 17:22














  • 1





    Since Angular 6.1 we can use { scrollPositionRestoration: 'enabled' } on eagerly loaded modules or just in app.module and it will be applied to all routes. RouterModule.forRoot(appRoutes, { scrollPositionRestoration: 'enabled' })

    – Manwal
    Mar 16 at 17:22








1




1





Since Angular 6.1 we can use { scrollPositionRestoration: 'enabled' } on eagerly loaded modules or just in app.module and it will be applied to all routes. RouterModule.forRoot(appRoutes, { scrollPositionRestoration: 'enabled' })

– Manwal
Mar 16 at 17:22





Since Angular 6.1 we can use { scrollPositionRestoration: 'enabled' } on eagerly loaded modules or just in app.module and it will be applied to all routes. RouterModule.forRoot(appRoutes, { scrollPositionRestoration: 'enabled' })

– Manwal
Mar 16 at 17:22












19 Answers
19






active

oldest

votes


















292














You can register a route change listener on your main component and scroll to top on route changes.



import { Component, OnInit } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';

@Component({
selector: 'my-app',
template: '<ng-content></ng-content>',
})
export class MyAppComponent implements OnInit {
constructor(private router: Router) { }

ngOnInit() {
this.router.events.subscribe((evt) => {
if (!(evt instanceof NavigationEnd)) {
return;
}
window.scrollTo(0, 0)
});
}
}





share|improve this answer





















  • 8





    window.scrollTo(0, 0) is a more concise than document.body.scrollTop = 0;, and more readable IMO.

    – Mark E. Haase
    Dec 30 '16 at 3:38






  • 8





    Did anybody noticed, that even after implementing this, issue persists in safari browser of Iphone. any thoughts?

    – rgk
    Jan 5 '17 at 17:11








  • 1





    @mehaase Looks like your answer is the best one. window.body.scrollTop doesn't work for me on Firefox desktop. So thank you !

    – KCarnaille
    Mar 2 '17 at 8:51






  • 3





    This worked for me, but it breaks the default "back" button behavior. Going back should remember the previous scroll position.

    – JackKalish
    Jun 13 '17 at 20:35






  • 6





    This worked!! Although I added $("body").animate({ scrollTop: 0 }, 1000); rather than window.scrollTo(0, 0) to animate smooth scrolling to top

    – Manubhargav
    Jul 5 '17 at 10:18





















175














Angular 6.1 and later:



Angular 6.1 (released on 2018-07-25) added built-in support to handle this issue, through a feature called "Router Scroll Position Restoration". As described in the official Angular blog, you just need to enable this in the router configuration like this:



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


Furthermore, the blog states "It is expected that this will become the default in a future major release". So far this hasn't happened (as of Angular 7.x), but eventually you won't need to do anything at all in your code, and this will just work correctly out of the box.



Angular 6.0 and earlier:



While @GuilhermeMeireles's excellent answer fixes the original problem, it introduces a new one, by breaking the normal behavior you expect when you navigate back or forward (with browser buttons or via Location in code). 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 obviously breaks this expectation.



The code below expands the logic to detect this kind of navigation by subscribing to Location's PopStateEvent sequence and skipping the scroll-to-top logic if the newly arrived-at page is a result of such an event.



If the page you navigate back from is long enough to cover the whole viewport, the scroll position is restored automatically, but as @JordanNelson correctly pointed out, if the page is shorter you need to keep track of the original y scroll position and restored it explicitly when you go back to the page. The updated version of the code covers this case too, by always explicitly restoring the scroll position.



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





share|improve this answer





















  • 2





    This should go either in the app component directly, or in a single component used in it (and therefore shared by the whole app). For instance, I've included it in a top navigation bar component. You should not included in all your components.

    – Fernando Echeverria
    Jun 28 '17 at 2:21






  • 3





    You can do that and it will make the code more widely compatible with other, non-browser, platforms. See stackoverflow.com/q/34177221/2858481 for implementation details.

    – Fernando Echeverria
    Jun 28 '17 at 13:26








  • 3





    This should be the accepted answer, so it does not break forward back behavior.

    – Ray Suelzer
    Nov 28 '17 at 3:53






  • 3





    If you click and hold the back/forward button in modern browsers, a menu appears that lets you navigate to locations other than your immediately previous/next one. This solution breaks if you do that. It's an edge case for most, but worth mentioning.

    – adamdport
    Nov 30 '17 at 17:28






  • 1





    I just posted a more concise solution based on this one, which works with the popstate mechanisms provided by Angular and restores scroll levels across multiple consecutive navigation events

    – Simon Mathewson
    Jul 10 '18 at 22:50





















40














From Angular 6.1, you can now avoid the hassle and pass extraOptions to your RouterModule.forRoot() as a second parameter and can specify scrollPositionRestoration: enabled to tell Angular to scroll to top whenever the route changes.



By default you will find this in app-routing.module.ts:



const routes: Routes = [
{
path: '...'
component: ...
},
...
];

@NgModule({
imports: [
RouterModule.forRoot(routes, {
scrollPositionRestoration: 'enabled', // Add options right here
})
],
exports: [RouterModule]
})
export class AppRoutingModule { }


Angular Official Docs






share|improve this answer

































    27














    You can write this more succinctly by taking advantage of the observable filter method:



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


    If you're having issues scrolling to the top when using the Angular Material 2 sidenav this will help. The window or document body won't have the scrollbar so you need to get the sidenav content container and scroll that element, otherwise try scrolling the window as a default.



    this.router.events.filter(event => event instanceof NavigationEnd)
    .subscribe(() => {
    const contentContainer = document.querySelector('.mat-sidenav-content') || this.window;
    contentContainer.scrollTo(0, 0);
    });


    Also, the Angular CDK v6.x has a scrolling package now that might help with handling scrolling.






    share|improve this answer





















    • 2





      Great! For me that worked - document.querySelector('.mat-sidenav-content .content-div').scrollTop = 0;

      – Amir Tugi
      Jun 3 '17 at 16:53











    • Nice one fellas... at mtpultz & @AmirTugi. Dealing with this right now, and you nailed it for me, cheers! Probably will inevitably end up rolling my own side nav since Material 2's doesn't play nice when md-toolbar is position:fixed (at top). Unless you guys have ideas....????

      – Tim Harker
      Jul 28 '17 at 13:56













    • Might have found my answer... stackoverflow.com/a/40396105/3389046

      – Tim Harker
      Jul 28 '17 at 14:24



















    15














    If you have server side rendering, you should be careful not to run the code using windows on the server, where that variable doesn't exist. It would result in code breaking.



    export class AppComponent implements OnInit {
    routerSubscription: Subscription;

    constructor(private router: Router,
    @Inject(PLATFORM_ID) private platformId: any) {}

    ngOnInit() {
    if (isPlatformBrowser(this.platformId)) {
    this.routerSubscription = this.router.events
    .filter(event => event instanceof NavigationEnd)
    .subscribe(event => {
    window.scrollTo(0, 0);
    });
    }
    }

    ngOnDestroy() {
    this.routerSubscription.unsubscribe();
    }
    }


    isPlatformBrowser is a function used to check if the current platform where the app is rendered is a browser or not. We give it the injected platformId.



    It it also possible to check for existence of variable windows, to be safe, like this:



    if (typeof window != 'undefined')





    share|improve this answer





















    • 1





      Don't you need to inject PLATFORM_ID in the constructor and give this value as parameter in de isPlatformBrowser method?

      – PierreDuc
      Dec 18 '17 at 10:41






    • 1





      @PierreDuc Yes, the answer is wrong. isPlatformBrowser is a function and will always be truthy. I've edited it now.

      – Lazar Ljubenović
      Jan 14 '18 at 19:30













    • Thanks! It's correct now! Just verified the API: github.com/angular/angular/blob/…

      – Raptor
      Jan 15 '18 at 2:52



















    12














    just do it easy with click action



    in your main component html make reference #scrollContainer



    <div class="main-container" #scrollContainer>
    <router-outlet (activate)="onActivate($event, scrollContainer)"></router-outlet>
    </div>


    in main component .ts



    onActivate(e, scrollContainer) {
    scrollContainer.scrollTop = 0;
    }





    share|improve this answer


























    • The element to be scrolled might not be in the scrollContainer first node, you might need to dig a bit in the object, for me what it really worked was scrollContainer .scrollable._elementRef.nativeElement.scrollTop = 0

      – Byron Lopez
      Mar 16 '18 at 22:19



















    10














    The best answer resides in the Angular GitHub discussion (Changing route doesn't scroll to top in the new page).




    Maybe you want go to top only in root router changes (not in children,
    because you can load routes with lazy load in f.e. a tabset)




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


    Full credits to JoniJnm (original post)






    share|improve this answer

































      6














      You can add the AfterViewInit lifecycle hook to your component.



      ngAfterViewInit() {
      window.scrollTo(0, 0);
      }





      share|improve this answer































        4














        Here's a solution that I've come up with. I paired up the LocationStrategy with the Router events. Using the LocationStrategy to set a boolean to know when a user's currently traversing through the browser history. This way, I don't have to store a bunch of URL and y-scroll data (which doesn't work well anyway, since each data is replaced based on URL). This also solves the edge case when a user decides to hold the back or forward button on a browser and goes back or forward multiple pages rather than just one.



        P.S. I've only tested on the latest version of IE, Chrome, FireFox, Safari, and Opera (as of this post).



        Hope this helps.



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





        share|improve this answer

































          3














          If you need simply scroll page to top, you can do this (not the best solution, but fast)



          document.getElementById('elementId').scrollTop = 0;





          share|improve this answer































            3














            This solution is based on @FernandoEcheverria's and @GuilhermeMeireles's solution, but it is more concise and works with the popstate mechanisms that the Angular Router provides. This allows for storing and restoring the scroll level of multiple consecutive navigations.



            We store the scroll positions for each navigation state in a map scrollLevels. Once there is a popstate event, the ID of the state that is about to be restored is supplied by the Angular Router: event.restoredState.navigationId. This is then used to get the last scroll level of that state from scrollLevels.



            If there is no stored scroll level for the route, it will scroll to the top as you would expect.



            import { Component, OnInit } from '@angular/core';
            import { Router, NavigationStart, NavigationEnd } from '@angular/router';

            @Component({
            selector: 'my-app',
            template: '<ng-content></ng-content>',
            })
            export class AppComponent implements OnInit {

            constructor(private router: Router) { }

            ngOnInit() {
            const scrollLevels: { [navigationId: number]: number } = {};
            let lastId = 0;
            let restoredId: number;

            this.router.events.subscribe((event: Event) => {

            if (event instanceof NavigationStart) {
            scrollLevels[lastId] = window.scrollY;
            lastId = event.id;
            restoredId = event.restoredState ? event.restoredState.navigationId : undefined;
            }

            if (event instanceof NavigationEnd) {
            if (restoredId) {
            // Optional: Wrap a timeout around the next line to wait for
            // the component to finish loading
            window.scrollTo(0, scrollLevels[restoredId] || 0);
            } else {
            window.scrollTo(0, 0);
            }
            }

            });
            }

            }





            share|improve this answer


























            • Awesome. I had to make a slightly custom version to scroll a div rather than window, but it worked. One key difference was scrollTop vs scrollY.

              – BBaysinger
              Jul 18 '18 at 3:35



















            3














            As of Angular 6.1, the router provides a configuration option called scrollPositionRestoration, this is designed to cater for this scenario.



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





            share|improve this answer































              1














              for iphone/ios safari you can wrap with a setTimeout



              setTimeout(function(){
              window.scrollTo(0, 1);
              }, 0);





              share|improve this answer


























              • in my case it also required the page wrapping element css to be set to; height: 100vh + 1px;

                – tubbsy
                Mar 10 '17 at 17:52





















              1














              Hi guys this works for me in angular 4. You just have to reference the parent to scroll on router change`



              layout.component.pug



              .wrapper(#outlet="")
              router-outlet((activate)='routerActivate($event,outlet)')


              layout.component.ts



               public routerActivate(event,outlet){
              outlet.scrollTop = 0;
              }`





              share|improve this answer



















              • 1





                pardon my laziness in not bothering to learn pug, but can you translate to HTML?

                – CodyBugstein
                Feb 9 '18 at 16:47



















              0














              @Fernando Echeverria
              great! but this code not work in hash router or lazy router. because they do not trigger location changes.
              can try this:






              private lastRouteUrl: string = 


              ngOnInit(): void {
              this.router.events.subscribe((ev) => {
              const len = this.lastRouteUrl.length
              if (ev instanceof NavigationEnd) {
              this.lastRouteUrl.push(ev.url)
              if (len > 1 && ev.url === this.lastRouteUrl[len - 2]) {
              return
              }
              window.scrollTo(0, 0)
              }
              })
              }








              share|improve this answer































                0














                Using the Router itself will cause issues which you cannot completely overcome to maintain consistent browser experience. In my opinion the best method is to just use a custom directive and let this reset the scroll on click. The good thing about this, is that if you are on the same url as that you click on, the page will scroll back to the top as well. This is consistent with normal websites. The basic directive could look something like this:



                import {Directive, HostListener} from '@angular/core';

                @Directive({
                selector: '[linkToTop]'
                })
                export class LinkToTopDirective {

                @HostListener('click')
                onClick(): void {
                window.scrollTo(0, 0);
                }
                }


                With the following usage:



                <a routerLink="/" linkToTop></a>


                This will be enough for most use-cases, but I can imagine a few issues which may
                arise from this:




                • Doesn't work on universal because of the usage of window

                • Small speed impact on change detection, because it is triggered by every click

                • No way to disable this directive


                It is actually quite easy to overcome these issues:



                @Directive({
                selector: '[linkToTop]'
                })
                export class LinkToTopDirective implements OnInit, OnDestroy {

                @Input()
                set linkToTop(active: string | boolean) {
                this.active = typeof active === 'string' ? active.length === 0 : active;
                }

                private active: boolean = true;

                private onClick: EventListener = (event: MouseEvent) => {
                if (this.active) {
                window.scrollTo(0, 0);
                }
                };

                constructor(@Inject(PLATFORM_ID) private readonly platformId: Object,
                private readonly elementRef: ElementRef,
                private readonly ngZone: NgZone
                ) {}

                ngOnDestroy(): void {
                if (isPlatformBrowser(this.platformId)) {
                this.elementRef.nativeElement.removeEventListener('click', this.onClick, false);
                }
                }

                ngOnInit(): void {
                if (isPlatformBrowser(this.platformId)) {
                this.ngZone.runOutsideAngular(() =>
                this.elementRef.nativeElement.addEventListener('click', this.onClick, false)
                );
                }
                }
                }


                This takes most use-cases into account, with the same usage as the basic one, with the advantage of enable/disabling it:



                <a routerLink="/" linkToTop></a> <!-- always active -->
                <a routerLink="/" [linkToTop]="isActive"> <!-- active when `isActive` is true -->


                commercials, don't read if you don't want to be advertised



                Another improvement could be made to check whether or not the browser supports passive events. This will complicate the code a bit more, and is a bit obscure if you want to implement all these in your custom directives/templates. That's why I wrote a little library which you can use to address these problems. To have the same functionality as above, and with the added passive event, you can change your directive to this, if you use the ng-event-options library. The logic is inside the click.pnb listener:



                @Directive({
                selector: '[linkToTop]'
                })
                export class LinkToTopDirective {

                @Input()
                set linkToTop(active: string|boolean) {
                this.active = typeof active === 'string' ? active.length === 0 : active;
                }

                private active: boolean = true;

                @HostListener('click.pnb')
                onClick(): void {
                if (this.active) {
                window.scrollTo(0, 0);
                }
                }
                }





                share|improve this answer

































                  0














                  This worked for me best for all navigation changes including hash navigation



                  constructor(private route: ActivatedRoute) {}

                  ngOnInit() {
                  this._sub = this.route.fragment.subscribe((hash: string) => {
                  if (hash) {
                  const cmp = document.getElementById(hash);
                  if (cmp) {
                  cmp.scrollIntoView();
                  }
                  } else {
                  window.scrollTo(0, 0);
                  }
                  });
                  }







                  share|improve this answer































                    0














                    The main idea behind this code is to keep all visited urls along with respective scrollY data in an array. Every time a user abandons a page (NavigationStart) this array is updated. Every time a user enters a new page (NavigationEnd), we decide to restore Y position or don't depending on how do we get to this page. If a refernce on some page was used we scroll to 0. If browser back/forward features were used we scroll to Y saved in our array. Sorry for my English :)



                    import { Component, OnInit, OnDestroy } from '@angular/core';
                    import { Location, PopStateEvent } from '@angular/common';
                    import { Router, Route, RouterLink, NavigationStart, NavigationEnd,
                    RouterEvent } from '@angular/router';
                    import { Subscription } from 'rxjs/Subscription';

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

                    private _subscription: Subscription;
                    private _scrollHistory: { url: string, y: number } = ;
                    private _useHistory = false;

                    constructor(
                    private _router: Router,
                    private _location: Location) {
                    }

                    public ngOnInit() {

                    this._subscription = this._router.events.subscribe((event: any) =>
                    {
                    if (event instanceof NavigationStart) {
                    const currentUrl = (this._location.path() !== '')
                    this._location.path() : '/';
                    const item = this._scrollHistory.find(x => x.url === currentUrl);
                    if (item) {
                    item.y = window.scrollY;
                    } else {
                    this._scrollHistory.push({ url: currentUrl, y: window.scrollY });
                    }
                    return;
                    }
                    if (event instanceof NavigationEnd) {
                    if (this._useHistory) {
                    this._useHistory = false;
                    window.scrollTo(0, this._scrollHistory.find(x => x.url ===
                    event.url).y);
                    } else {
                    window.scrollTo(0, 0);
                    }
                    }
                    });

                    this._subscription.add(this._location.subscribe((event: PopStateEvent)
                    => { this._useHistory = true;
                    }));
                    }

                    public ngOnDestroy(): void {
                    this._subscription.unsubscribe();
                    }
                    }





                    share|improve this answer































                      0














                      window.scrollTo() doesn't work for me in Angular 5, so I have used document.body.scrollTop like,



                      this.router.events.subscribe((evt) => {
                      if (evt instanceof NavigationEnd) {
                      document.body.scrollTop = 0;
                      }
                      });





                      share|improve this answer






















                        protected by eyllanesc Apr 15 '18 at 7:07



                        Thank you for your interest in this question.
                        Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).



                        Would you like to answer one of these unanswered questions instead?














                        19 Answers
                        19






                        active

                        oldest

                        votes








                        19 Answers
                        19






                        active

                        oldest

                        votes









                        active

                        oldest

                        votes






                        active

                        oldest

                        votes









                        292














                        You can register a route change listener on your main component and scroll to top on route changes.



                        import { Component, OnInit } from '@angular/core';
                        import { Router, NavigationEnd } from '@angular/router';

                        @Component({
                        selector: 'my-app',
                        template: '<ng-content></ng-content>',
                        })
                        export class MyAppComponent implements OnInit {
                        constructor(private router: Router) { }

                        ngOnInit() {
                        this.router.events.subscribe((evt) => {
                        if (!(evt instanceof NavigationEnd)) {
                        return;
                        }
                        window.scrollTo(0, 0)
                        });
                        }
                        }





                        share|improve this answer





















                        • 8





                          window.scrollTo(0, 0) is a more concise than document.body.scrollTop = 0;, and more readable IMO.

                          – Mark E. Haase
                          Dec 30 '16 at 3:38






                        • 8





                          Did anybody noticed, that even after implementing this, issue persists in safari browser of Iphone. any thoughts?

                          – rgk
                          Jan 5 '17 at 17:11








                        • 1





                          @mehaase Looks like your answer is the best one. window.body.scrollTop doesn't work for me on Firefox desktop. So thank you !

                          – KCarnaille
                          Mar 2 '17 at 8:51






                        • 3





                          This worked for me, but it breaks the default "back" button behavior. Going back should remember the previous scroll position.

                          – JackKalish
                          Jun 13 '17 at 20:35






                        • 6





                          This worked!! Although I added $("body").animate({ scrollTop: 0 }, 1000); rather than window.scrollTo(0, 0) to animate smooth scrolling to top

                          – Manubhargav
                          Jul 5 '17 at 10:18


















                        292














                        You can register a route change listener on your main component and scroll to top on route changes.



                        import { Component, OnInit } from '@angular/core';
                        import { Router, NavigationEnd } from '@angular/router';

                        @Component({
                        selector: 'my-app',
                        template: '<ng-content></ng-content>',
                        })
                        export class MyAppComponent implements OnInit {
                        constructor(private router: Router) { }

                        ngOnInit() {
                        this.router.events.subscribe((evt) => {
                        if (!(evt instanceof NavigationEnd)) {
                        return;
                        }
                        window.scrollTo(0, 0)
                        });
                        }
                        }





                        share|improve this answer





















                        • 8





                          window.scrollTo(0, 0) is a more concise than document.body.scrollTop = 0;, and more readable IMO.

                          – Mark E. Haase
                          Dec 30 '16 at 3:38






                        • 8





                          Did anybody noticed, that even after implementing this, issue persists in safari browser of Iphone. any thoughts?

                          – rgk
                          Jan 5 '17 at 17:11








                        • 1





                          @mehaase Looks like your answer is the best one. window.body.scrollTop doesn't work for me on Firefox desktop. So thank you !

                          – KCarnaille
                          Mar 2 '17 at 8:51






                        • 3





                          This worked for me, but it breaks the default "back" button behavior. Going back should remember the previous scroll position.

                          – JackKalish
                          Jun 13 '17 at 20:35






                        • 6





                          This worked!! Although I added $("body").animate({ scrollTop: 0 }, 1000); rather than window.scrollTo(0, 0) to animate smooth scrolling to top

                          – Manubhargav
                          Jul 5 '17 at 10:18
















                        292












                        292








                        292







                        You can register a route change listener on your main component and scroll to top on route changes.



                        import { Component, OnInit } from '@angular/core';
                        import { Router, NavigationEnd } from '@angular/router';

                        @Component({
                        selector: 'my-app',
                        template: '<ng-content></ng-content>',
                        })
                        export class MyAppComponent implements OnInit {
                        constructor(private router: Router) { }

                        ngOnInit() {
                        this.router.events.subscribe((evt) => {
                        if (!(evt instanceof NavigationEnd)) {
                        return;
                        }
                        window.scrollTo(0, 0)
                        });
                        }
                        }





                        share|improve this answer















                        You can register a route change listener on your main component and scroll to top on route changes.



                        import { Component, OnInit } from '@angular/core';
                        import { Router, NavigationEnd } from '@angular/router';

                        @Component({
                        selector: 'my-app',
                        template: '<ng-content></ng-content>',
                        })
                        export class MyAppComponent implements OnInit {
                        constructor(private router: Router) { }

                        ngOnInit() {
                        this.router.events.subscribe((evt) => {
                        if (!(evt instanceof NavigationEnd)) {
                        return;
                        }
                        window.scrollTo(0, 0)
                        });
                        }
                        }






                        share|improve this answer














                        share|improve this answer



                        share|improve this answer








                        edited Mar 3 '17 at 13:51

























                        answered Sep 20 '16 at 19:06









                        Guilherme MeirelesGuilherme Meireles

                        5,36321514




                        5,36321514








                        • 8





                          window.scrollTo(0, 0) is a more concise than document.body.scrollTop = 0;, and more readable IMO.

                          – Mark E. Haase
                          Dec 30 '16 at 3:38






                        • 8





                          Did anybody noticed, that even after implementing this, issue persists in safari browser of Iphone. any thoughts?

                          – rgk
                          Jan 5 '17 at 17:11








                        • 1





                          @mehaase Looks like your answer is the best one. window.body.scrollTop doesn't work for me on Firefox desktop. So thank you !

                          – KCarnaille
                          Mar 2 '17 at 8:51






                        • 3





                          This worked for me, but it breaks the default "back" button behavior. Going back should remember the previous scroll position.

                          – JackKalish
                          Jun 13 '17 at 20:35






                        • 6





                          This worked!! Although I added $("body").animate({ scrollTop: 0 }, 1000); rather than window.scrollTo(0, 0) to animate smooth scrolling to top

                          – Manubhargav
                          Jul 5 '17 at 10:18
















                        • 8





                          window.scrollTo(0, 0) is a more concise than document.body.scrollTop = 0;, and more readable IMO.

                          – Mark E. Haase
                          Dec 30 '16 at 3:38






                        • 8





                          Did anybody noticed, that even after implementing this, issue persists in safari browser of Iphone. any thoughts?

                          – rgk
                          Jan 5 '17 at 17:11








                        • 1





                          @mehaase Looks like your answer is the best one. window.body.scrollTop doesn't work for me on Firefox desktop. So thank you !

                          – KCarnaille
                          Mar 2 '17 at 8:51






                        • 3





                          This worked for me, but it breaks the default "back" button behavior. Going back should remember the previous scroll position.

                          – JackKalish
                          Jun 13 '17 at 20:35






                        • 6





                          This worked!! Although I added $("body").animate({ scrollTop: 0 }, 1000); rather than window.scrollTo(0, 0) to animate smooth scrolling to top

                          – Manubhargav
                          Jul 5 '17 at 10:18










                        8




                        8





                        window.scrollTo(0, 0) is a more concise than document.body.scrollTop = 0;, and more readable IMO.

                        – Mark E. Haase
                        Dec 30 '16 at 3:38





                        window.scrollTo(0, 0) is a more concise than document.body.scrollTop = 0;, and more readable IMO.

                        – Mark E. Haase
                        Dec 30 '16 at 3:38




                        8




                        8





                        Did anybody noticed, that even after implementing this, issue persists in safari browser of Iphone. any thoughts?

                        – rgk
                        Jan 5 '17 at 17:11







                        Did anybody noticed, that even after implementing this, issue persists in safari browser of Iphone. any thoughts?

                        – rgk
                        Jan 5 '17 at 17:11






                        1




                        1





                        @mehaase Looks like your answer is the best one. window.body.scrollTop doesn't work for me on Firefox desktop. So thank you !

                        – KCarnaille
                        Mar 2 '17 at 8:51





                        @mehaase Looks like your answer is the best one. window.body.scrollTop doesn't work for me on Firefox desktop. So thank you !

                        – KCarnaille
                        Mar 2 '17 at 8:51




                        3




                        3





                        This worked for me, but it breaks the default "back" button behavior. Going back should remember the previous scroll position.

                        – JackKalish
                        Jun 13 '17 at 20:35





                        This worked for me, but it breaks the default "back" button behavior. Going back should remember the previous scroll position.

                        – JackKalish
                        Jun 13 '17 at 20:35




                        6




                        6





                        This worked!! Although I added $("body").animate({ scrollTop: 0 }, 1000); rather than window.scrollTo(0, 0) to animate smooth scrolling to top

                        – Manubhargav
                        Jul 5 '17 at 10:18







                        This worked!! Although I added $("body").animate({ scrollTop: 0 }, 1000); rather than window.scrollTo(0, 0) to animate smooth scrolling to top

                        – Manubhargav
                        Jul 5 '17 at 10:18















                        175














                        Angular 6.1 and later:



                        Angular 6.1 (released on 2018-07-25) added built-in support to handle this issue, through a feature called "Router Scroll Position Restoration". As described in the official Angular blog, you just need to enable this in the router configuration like this:



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


                        Furthermore, the blog states "It is expected that this will become the default in a future major release". So far this hasn't happened (as of Angular 7.x), but eventually you won't need to do anything at all in your code, and this will just work correctly out of the box.



                        Angular 6.0 and earlier:



                        While @GuilhermeMeireles's excellent answer fixes the original problem, it introduces a new one, by breaking the normal behavior you expect when you navigate back or forward (with browser buttons or via Location in code). 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 obviously breaks this expectation.



                        The code below expands the logic to detect this kind of navigation by subscribing to Location's PopStateEvent sequence and skipping the scroll-to-top logic if the newly arrived-at page is a result of such an event.



                        If the page you navigate back from is long enough to cover the whole viewport, the scroll position is restored automatically, but as @JordanNelson correctly pointed out, if the page is shorter you need to keep track of the original y scroll position and restored it explicitly when you go back to the page. The updated version of the code covers this case too, by always explicitly restoring the scroll position.



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





                        share|improve this answer





















                        • 2





                          This should go either in the app component directly, or in a single component used in it (and therefore shared by the whole app). For instance, I've included it in a top navigation bar component. You should not included in all your components.

                          – Fernando Echeverria
                          Jun 28 '17 at 2:21






                        • 3





                          You can do that and it will make the code more widely compatible with other, non-browser, platforms. See stackoverflow.com/q/34177221/2858481 for implementation details.

                          – Fernando Echeverria
                          Jun 28 '17 at 13:26








                        • 3





                          This should be the accepted answer, so it does not break forward back behavior.

                          – Ray Suelzer
                          Nov 28 '17 at 3:53






                        • 3





                          If you click and hold the back/forward button in modern browsers, a menu appears that lets you navigate to locations other than your immediately previous/next one. This solution breaks if you do that. It's an edge case for most, but worth mentioning.

                          – adamdport
                          Nov 30 '17 at 17:28






                        • 1





                          I just posted a more concise solution based on this one, which works with the popstate mechanisms provided by Angular and restores scroll levels across multiple consecutive navigation events

                          – Simon Mathewson
                          Jul 10 '18 at 22:50


















                        175














                        Angular 6.1 and later:



                        Angular 6.1 (released on 2018-07-25) added built-in support to handle this issue, through a feature called "Router Scroll Position Restoration". As described in the official Angular blog, you just need to enable this in the router configuration like this:



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


                        Furthermore, the blog states "It is expected that this will become the default in a future major release". So far this hasn't happened (as of Angular 7.x), but eventually you won't need to do anything at all in your code, and this will just work correctly out of the box.



                        Angular 6.0 and earlier:



                        While @GuilhermeMeireles's excellent answer fixes the original problem, it introduces a new one, by breaking the normal behavior you expect when you navigate back or forward (with browser buttons or via Location in code). 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 obviously breaks this expectation.



                        The code below expands the logic to detect this kind of navigation by subscribing to Location's PopStateEvent sequence and skipping the scroll-to-top logic if the newly arrived-at page is a result of such an event.



                        If the page you navigate back from is long enough to cover the whole viewport, the scroll position is restored automatically, but as @JordanNelson correctly pointed out, if the page is shorter you need to keep track of the original y scroll position and restored it explicitly when you go back to the page. The updated version of the code covers this case too, by always explicitly restoring the scroll position.



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





                        share|improve this answer





















                        • 2





                          This should go either in the app component directly, or in a single component used in it (and therefore shared by the whole app). For instance, I've included it in a top navigation bar component. You should not included in all your components.

                          – Fernando Echeverria
                          Jun 28 '17 at 2:21






                        • 3





                          You can do that and it will make the code more widely compatible with other, non-browser, platforms. See stackoverflow.com/q/34177221/2858481 for implementation details.

                          – Fernando Echeverria
                          Jun 28 '17 at 13:26








                        • 3





                          This should be the accepted answer, so it does not break forward back behavior.

                          – Ray Suelzer
                          Nov 28 '17 at 3:53






                        • 3





                          If you click and hold the back/forward button in modern browsers, a menu appears that lets you navigate to locations other than your immediately previous/next one. This solution breaks if you do that. It's an edge case for most, but worth mentioning.

                          – adamdport
                          Nov 30 '17 at 17:28






                        • 1





                          I just posted a more concise solution based on this one, which works with the popstate mechanisms provided by Angular and restores scroll levels across multiple consecutive navigation events

                          – Simon Mathewson
                          Jul 10 '18 at 22:50
















                        175












                        175








                        175







                        Angular 6.1 and later:



                        Angular 6.1 (released on 2018-07-25) added built-in support to handle this issue, through a feature called "Router Scroll Position Restoration". As described in the official Angular blog, you just need to enable this in the router configuration like this:



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


                        Furthermore, the blog states "It is expected that this will become the default in a future major release". So far this hasn't happened (as of Angular 7.x), but eventually you won't need to do anything at all in your code, and this will just work correctly out of the box.



                        Angular 6.0 and earlier:



                        While @GuilhermeMeireles's excellent answer fixes the original problem, it introduces a new one, by breaking the normal behavior you expect when you navigate back or forward (with browser buttons or via Location in code). 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 obviously breaks this expectation.



                        The code below expands the logic to detect this kind of navigation by subscribing to Location's PopStateEvent sequence and skipping the scroll-to-top logic if the newly arrived-at page is a result of such an event.



                        If the page you navigate back from is long enough to cover the whole viewport, the scroll position is restored automatically, but as @JordanNelson correctly pointed out, if the page is shorter you need to keep track of the original y scroll position and restored it explicitly when you go back to the page. The updated version of the code covers this case too, by always explicitly restoring the scroll position.



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





                        share|improve this answer















                        Angular 6.1 and later:



                        Angular 6.1 (released on 2018-07-25) added built-in support to handle this issue, through a feature called "Router Scroll Position Restoration". As described in the official Angular blog, you just need to enable this in the router configuration like this:



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


                        Furthermore, the blog states "It is expected that this will become the default in a future major release". So far this hasn't happened (as of Angular 7.x), but eventually you won't need to do anything at all in your code, and this will just work correctly out of the box.



                        Angular 6.0 and earlier:



                        While @GuilhermeMeireles's excellent answer fixes the original problem, it introduces a new one, by breaking the normal behavior you expect when you navigate back or forward (with browser buttons or via Location in code). 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 obviously breaks this expectation.



                        The code below expands the logic to detect this kind of navigation by subscribing to Location's PopStateEvent sequence and skipping the scroll-to-top logic if the newly arrived-at page is a result of such an event.



                        If the page you navigate back from is long enough to cover the whole viewport, the scroll position is restored automatically, but as @JordanNelson correctly pointed out, if the page is shorter you need to keep track of the original y scroll position and restored it explicitly when you go back to the page. The updated version of the code covers this case too, by always explicitly restoring the scroll position.



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






                        share|improve this answer














                        share|improve this answer



                        share|improve this answer








                        edited Mar 7 at 20:50

























                        answered Jun 5 '17 at 15:17









                        Fernando EcheverriaFernando Echeverria

                        3,40041012




                        3,40041012








                        • 2





                          This should go either in the app component directly, or in a single component used in it (and therefore shared by the whole app). For instance, I've included it in a top navigation bar component. You should not included in all your components.

                          – Fernando Echeverria
                          Jun 28 '17 at 2:21






                        • 3





                          You can do that and it will make the code more widely compatible with other, non-browser, platforms. See stackoverflow.com/q/34177221/2858481 for implementation details.

                          – Fernando Echeverria
                          Jun 28 '17 at 13:26








                        • 3





                          This should be the accepted answer, so it does not break forward back behavior.

                          – Ray Suelzer
                          Nov 28 '17 at 3:53






                        • 3





                          If you click and hold the back/forward button in modern browsers, a menu appears that lets you navigate to locations other than your immediately previous/next one. This solution breaks if you do that. It's an edge case for most, but worth mentioning.

                          – adamdport
                          Nov 30 '17 at 17:28






                        • 1





                          I just posted a more concise solution based on this one, which works with the popstate mechanisms provided by Angular and restores scroll levels across multiple consecutive navigation events

                          – Simon Mathewson
                          Jul 10 '18 at 22:50
















                        • 2





                          This should go either in the app component directly, or in a single component used in it (and therefore shared by the whole app). For instance, I've included it in a top navigation bar component. You should not included in all your components.

                          – Fernando Echeverria
                          Jun 28 '17 at 2:21






                        • 3





                          You can do that and it will make the code more widely compatible with other, non-browser, platforms. See stackoverflow.com/q/34177221/2858481 for implementation details.

                          – Fernando Echeverria
                          Jun 28 '17 at 13:26








                        • 3





                          This should be the accepted answer, so it does not break forward back behavior.

                          – Ray Suelzer
                          Nov 28 '17 at 3:53






                        • 3





                          If you click and hold the back/forward button in modern browsers, a menu appears that lets you navigate to locations other than your immediately previous/next one. This solution breaks if you do that. It's an edge case for most, but worth mentioning.

                          – adamdport
                          Nov 30 '17 at 17:28






                        • 1





                          I just posted a more concise solution based on this one, which works with the popstate mechanisms provided by Angular and restores scroll levels across multiple consecutive navigation events

                          – Simon Mathewson
                          Jul 10 '18 at 22:50










                        2




                        2





                        This should go either in the app component directly, or in a single component used in it (and therefore shared by the whole app). For instance, I've included it in a top navigation bar component. You should not included in all your components.

                        – Fernando Echeverria
                        Jun 28 '17 at 2:21





                        This should go either in the app component directly, or in a single component used in it (and therefore shared by the whole app). For instance, I've included it in a top navigation bar component. You should not included in all your components.

                        – Fernando Echeverria
                        Jun 28 '17 at 2:21




                        3




                        3





                        You can do that and it will make the code more widely compatible with other, non-browser, platforms. See stackoverflow.com/q/34177221/2858481 for implementation details.

                        – Fernando Echeverria
                        Jun 28 '17 at 13:26







                        You can do that and it will make the code more widely compatible with other, non-browser, platforms. See stackoverflow.com/q/34177221/2858481 for implementation details.

                        – Fernando Echeverria
                        Jun 28 '17 at 13:26






                        3




                        3





                        This should be the accepted answer, so it does not break forward back behavior.

                        – Ray Suelzer
                        Nov 28 '17 at 3:53





                        This should be the accepted answer, so it does not break forward back behavior.

                        – Ray Suelzer
                        Nov 28 '17 at 3:53




                        3




                        3





                        If you click and hold the back/forward button in modern browsers, a menu appears that lets you navigate to locations other than your immediately previous/next one. This solution breaks if you do that. It's an edge case for most, but worth mentioning.

                        – adamdport
                        Nov 30 '17 at 17:28





                        If you click and hold the back/forward button in modern browsers, a menu appears that lets you navigate to locations other than your immediately previous/next one. This solution breaks if you do that. It's an edge case for most, but worth mentioning.

                        – adamdport
                        Nov 30 '17 at 17:28




                        1




                        1





                        I just posted a more concise solution based on this one, which works with the popstate mechanisms provided by Angular and restores scroll levels across multiple consecutive navigation events

                        – Simon Mathewson
                        Jul 10 '18 at 22:50







                        I just posted a more concise solution based on this one, which works with the popstate mechanisms provided by Angular and restores scroll levels across multiple consecutive navigation events

                        – Simon Mathewson
                        Jul 10 '18 at 22:50













                        40














                        From Angular 6.1, you can now avoid the hassle and pass extraOptions to your RouterModule.forRoot() as a second parameter and can specify scrollPositionRestoration: enabled to tell Angular to scroll to top whenever the route changes.



                        By default you will find this in app-routing.module.ts:



                        const routes: Routes = [
                        {
                        path: '...'
                        component: ...
                        },
                        ...
                        ];

                        @NgModule({
                        imports: [
                        RouterModule.forRoot(routes, {
                        scrollPositionRestoration: 'enabled', // Add options right here
                        })
                        ],
                        exports: [RouterModule]
                        })
                        export class AppRoutingModule { }


                        Angular Official Docs






                        share|improve this answer






























                          40














                          From Angular 6.1, you can now avoid the hassle and pass extraOptions to your RouterModule.forRoot() as a second parameter and can specify scrollPositionRestoration: enabled to tell Angular to scroll to top whenever the route changes.



                          By default you will find this in app-routing.module.ts:



                          const routes: Routes = [
                          {
                          path: '...'
                          component: ...
                          },
                          ...
                          ];

                          @NgModule({
                          imports: [
                          RouterModule.forRoot(routes, {
                          scrollPositionRestoration: 'enabled', // Add options right here
                          })
                          ],
                          exports: [RouterModule]
                          })
                          export class AppRoutingModule { }


                          Angular Official Docs






                          share|improve this answer




























                            40












                            40








                            40







                            From Angular 6.1, you can now avoid the hassle and pass extraOptions to your RouterModule.forRoot() as a second parameter and can specify scrollPositionRestoration: enabled to tell Angular to scroll to top whenever the route changes.



                            By default you will find this in app-routing.module.ts:



                            const routes: Routes = [
                            {
                            path: '...'
                            component: ...
                            },
                            ...
                            ];

                            @NgModule({
                            imports: [
                            RouterModule.forRoot(routes, {
                            scrollPositionRestoration: 'enabled', // Add options right here
                            })
                            ],
                            exports: [RouterModule]
                            })
                            export class AppRoutingModule { }


                            Angular Official Docs






                            share|improve this answer















                            From Angular 6.1, you can now avoid the hassle and pass extraOptions to your RouterModule.forRoot() as a second parameter and can specify scrollPositionRestoration: enabled to tell Angular to scroll to top whenever the route changes.



                            By default you will find this in app-routing.module.ts:



                            const routes: Routes = [
                            {
                            path: '...'
                            component: ...
                            },
                            ...
                            ];

                            @NgModule({
                            imports: [
                            RouterModule.forRoot(routes, {
                            scrollPositionRestoration: 'enabled', // Add options right here
                            })
                            ],
                            exports: [RouterModule]
                            })
                            export class AppRoutingModule { }


                            Angular Official Docs







                            share|improve this answer














                            share|improve this answer



                            share|improve this answer








                            edited Nov 23 '18 at 14:37









                            Michael Czechowski

                            1,6571036




                            1,6571036










                            answered Aug 19 '18 at 7:52









                            Abdul RafayAbdul Rafay

                            1,6621028




                            1,6621028























                                27














                                You can write this more succinctly by taking advantage of the observable filter method:



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


                                If you're having issues scrolling to the top when using the Angular Material 2 sidenav this will help. The window or document body won't have the scrollbar so you need to get the sidenav content container and scroll that element, otherwise try scrolling the window as a default.



                                this.router.events.filter(event => event instanceof NavigationEnd)
                                .subscribe(() => {
                                const contentContainer = document.querySelector('.mat-sidenav-content') || this.window;
                                contentContainer.scrollTo(0, 0);
                                });


                                Also, the Angular CDK v6.x has a scrolling package now that might help with handling scrolling.






                                share|improve this answer





















                                • 2





                                  Great! For me that worked - document.querySelector('.mat-sidenav-content .content-div').scrollTop = 0;

                                  – Amir Tugi
                                  Jun 3 '17 at 16:53











                                • Nice one fellas... at mtpultz & @AmirTugi. Dealing with this right now, and you nailed it for me, cheers! Probably will inevitably end up rolling my own side nav since Material 2's doesn't play nice when md-toolbar is position:fixed (at top). Unless you guys have ideas....????

                                  – Tim Harker
                                  Jul 28 '17 at 13:56













                                • Might have found my answer... stackoverflow.com/a/40396105/3389046

                                  – Tim Harker
                                  Jul 28 '17 at 14:24
















                                27














                                You can write this more succinctly by taking advantage of the observable filter method:



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


                                If you're having issues scrolling to the top when using the Angular Material 2 sidenav this will help. The window or document body won't have the scrollbar so you need to get the sidenav content container and scroll that element, otherwise try scrolling the window as a default.



                                this.router.events.filter(event => event instanceof NavigationEnd)
                                .subscribe(() => {
                                const contentContainer = document.querySelector('.mat-sidenav-content') || this.window;
                                contentContainer.scrollTo(0, 0);
                                });


                                Also, the Angular CDK v6.x has a scrolling package now that might help with handling scrolling.






                                share|improve this answer





















                                • 2





                                  Great! For me that worked - document.querySelector('.mat-sidenav-content .content-div').scrollTop = 0;

                                  – Amir Tugi
                                  Jun 3 '17 at 16:53











                                • Nice one fellas... at mtpultz & @AmirTugi. Dealing with this right now, and you nailed it for me, cheers! Probably will inevitably end up rolling my own side nav since Material 2's doesn't play nice when md-toolbar is position:fixed (at top). Unless you guys have ideas....????

                                  – Tim Harker
                                  Jul 28 '17 at 13:56













                                • Might have found my answer... stackoverflow.com/a/40396105/3389046

                                  – Tim Harker
                                  Jul 28 '17 at 14:24














                                27












                                27








                                27







                                You can write this more succinctly by taking advantage of the observable filter method:



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


                                If you're having issues scrolling to the top when using the Angular Material 2 sidenav this will help. The window or document body won't have the scrollbar so you need to get the sidenav content container and scroll that element, otherwise try scrolling the window as a default.



                                this.router.events.filter(event => event instanceof NavigationEnd)
                                .subscribe(() => {
                                const contentContainer = document.querySelector('.mat-sidenav-content') || this.window;
                                contentContainer.scrollTo(0, 0);
                                });


                                Also, the Angular CDK v6.x has a scrolling package now that might help with handling scrolling.






                                share|improve this answer















                                You can write this more succinctly by taking advantage of the observable filter method:



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


                                If you're having issues scrolling to the top when using the Angular Material 2 sidenav this will help. The window or document body won't have the scrollbar so you need to get the sidenav content container and scroll that element, otherwise try scrolling the window as a default.



                                this.router.events.filter(event => event instanceof NavigationEnd)
                                .subscribe(() => {
                                const contentContainer = document.querySelector('.mat-sidenav-content') || this.window;
                                contentContainer.scrollTo(0, 0);
                                });


                                Also, the Angular CDK v6.x has a scrolling package now that might help with handling scrolling.







                                share|improve this answer














                                share|improve this answer



                                share|improve this answer








                                edited Jul 25 '18 at 16:17

























                                answered Apr 26 '17 at 6:55









                                mtpultzmtpultz

                                5,520864133




                                5,520864133








                                • 2





                                  Great! For me that worked - document.querySelector('.mat-sidenav-content .content-div').scrollTop = 0;

                                  – Amir Tugi
                                  Jun 3 '17 at 16:53











                                • Nice one fellas... at mtpultz & @AmirTugi. Dealing with this right now, and you nailed it for me, cheers! Probably will inevitably end up rolling my own side nav since Material 2's doesn't play nice when md-toolbar is position:fixed (at top). Unless you guys have ideas....????

                                  – Tim Harker
                                  Jul 28 '17 at 13:56













                                • Might have found my answer... stackoverflow.com/a/40396105/3389046

                                  – Tim Harker
                                  Jul 28 '17 at 14:24














                                • 2





                                  Great! For me that worked - document.querySelector('.mat-sidenav-content .content-div').scrollTop = 0;

                                  – Amir Tugi
                                  Jun 3 '17 at 16:53











                                • Nice one fellas... at mtpultz & @AmirTugi. Dealing with this right now, and you nailed it for me, cheers! Probably will inevitably end up rolling my own side nav since Material 2's doesn't play nice when md-toolbar is position:fixed (at top). Unless you guys have ideas....????

                                  – Tim Harker
                                  Jul 28 '17 at 13:56













                                • Might have found my answer... stackoverflow.com/a/40396105/3389046

                                  – Tim Harker
                                  Jul 28 '17 at 14:24








                                2




                                2





                                Great! For me that worked - document.querySelector('.mat-sidenav-content .content-div').scrollTop = 0;

                                – Amir Tugi
                                Jun 3 '17 at 16:53





                                Great! For me that worked - document.querySelector('.mat-sidenav-content .content-div').scrollTop = 0;

                                – Amir Tugi
                                Jun 3 '17 at 16:53













                                Nice one fellas... at mtpultz & @AmirTugi. Dealing with this right now, and you nailed it for me, cheers! Probably will inevitably end up rolling my own side nav since Material 2's doesn't play nice when md-toolbar is position:fixed (at top). Unless you guys have ideas....????

                                – Tim Harker
                                Jul 28 '17 at 13:56







                                Nice one fellas... at mtpultz & @AmirTugi. Dealing with this right now, and you nailed it for me, cheers! Probably will inevitably end up rolling my own side nav since Material 2's doesn't play nice when md-toolbar is position:fixed (at top). Unless you guys have ideas....????

                                – Tim Harker
                                Jul 28 '17 at 13:56















                                Might have found my answer... stackoverflow.com/a/40396105/3389046

                                – Tim Harker
                                Jul 28 '17 at 14:24





                                Might have found my answer... stackoverflow.com/a/40396105/3389046

                                – Tim Harker
                                Jul 28 '17 at 14:24











                                15














                                If you have server side rendering, you should be careful not to run the code using windows on the server, where that variable doesn't exist. It would result in code breaking.



                                export class AppComponent implements OnInit {
                                routerSubscription: Subscription;

                                constructor(private router: Router,
                                @Inject(PLATFORM_ID) private platformId: any) {}

                                ngOnInit() {
                                if (isPlatformBrowser(this.platformId)) {
                                this.routerSubscription = this.router.events
                                .filter(event => event instanceof NavigationEnd)
                                .subscribe(event => {
                                window.scrollTo(0, 0);
                                });
                                }
                                }

                                ngOnDestroy() {
                                this.routerSubscription.unsubscribe();
                                }
                                }


                                isPlatformBrowser is a function used to check if the current platform where the app is rendered is a browser or not. We give it the injected platformId.



                                It it also possible to check for existence of variable windows, to be safe, like this:



                                if (typeof window != 'undefined')





                                share|improve this answer





















                                • 1





                                  Don't you need to inject PLATFORM_ID in the constructor and give this value as parameter in de isPlatformBrowser method?

                                  – PierreDuc
                                  Dec 18 '17 at 10:41






                                • 1





                                  @PierreDuc Yes, the answer is wrong. isPlatformBrowser is a function and will always be truthy. I've edited it now.

                                  – Lazar Ljubenović
                                  Jan 14 '18 at 19:30













                                • Thanks! It's correct now! Just verified the API: github.com/angular/angular/blob/…

                                  – Raptor
                                  Jan 15 '18 at 2:52
















                                15














                                If you have server side rendering, you should be careful not to run the code using windows on the server, where that variable doesn't exist. It would result in code breaking.



                                export class AppComponent implements OnInit {
                                routerSubscription: Subscription;

                                constructor(private router: Router,
                                @Inject(PLATFORM_ID) private platformId: any) {}

                                ngOnInit() {
                                if (isPlatformBrowser(this.platformId)) {
                                this.routerSubscription = this.router.events
                                .filter(event => event instanceof NavigationEnd)
                                .subscribe(event => {
                                window.scrollTo(0, 0);
                                });
                                }
                                }

                                ngOnDestroy() {
                                this.routerSubscription.unsubscribe();
                                }
                                }


                                isPlatformBrowser is a function used to check if the current platform where the app is rendered is a browser or not. We give it the injected platformId.



                                It it also possible to check for existence of variable windows, to be safe, like this:



                                if (typeof window != 'undefined')





                                share|improve this answer





















                                • 1





                                  Don't you need to inject PLATFORM_ID in the constructor and give this value as parameter in de isPlatformBrowser method?

                                  – PierreDuc
                                  Dec 18 '17 at 10:41






                                • 1





                                  @PierreDuc Yes, the answer is wrong. isPlatformBrowser is a function and will always be truthy. I've edited it now.

                                  – Lazar Ljubenović
                                  Jan 14 '18 at 19:30













                                • Thanks! It's correct now! Just verified the API: github.com/angular/angular/blob/…

                                  – Raptor
                                  Jan 15 '18 at 2:52














                                15












                                15








                                15







                                If you have server side rendering, you should be careful not to run the code using windows on the server, where that variable doesn't exist. It would result in code breaking.



                                export class AppComponent implements OnInit {
                                routerSubscription: Subscription;

                                constructor(private router: Router,
                                @Inject(PLATFORM_ID) private platformId: any) {}

                                ngOnInit() {
                                if (isPlatformBrowser(this.platformId)) {
                                this.routerSubscription = this.router.events
                                .filter(event => event instanceof NavigationEnd)
                                .subscribe(event => {
                                window.scrollTo(0, 0);
                                });
                                }
                                }

                                ngOnDestroy() {
                                this.routerSubscription.unsubscribe();
                                }
                                }


                                isPlatformBrowser is a function used to check if the current platform where the app is rendered is a browser or not. We give it the injected platformId.



                                It it also possible to check for existence of variable windows, to be safe, like this:



                                if (typeof window != 'undefined')





                                share|improve this answer















                                If you have server side rendering, you should be careful not to run the code using windows on the server, where that variable doesn't exist. It would result in code breaking.



                                export class AppComponent implements OnInit {
                                routerSubscription: Subscription;

                                constructor(private router: Router,
                                @Inject(PLATFORM_ID) private platformId: any) {}

                                ngOnInit() {
                                if (isPlatformBrowser(this.platformId)) {
                                this.routerSubscription = this.router.events
                                .filter(event => event instanceof NavigationEnd)
                                .subscribe(event => {
                                window.scrollTo(0, 0);
                                });
                                }
                                }

                                ngOnDestroy() {
                                this.routerSubscription.unsubscribe();
                                }
                                }


                                isPlatformBrowser is a function used to check if the current platform where the app is rendered is a browser or not. We give it the injected platformId.



                                It it also possible to check for existence of variable windows, to be safe, like this:



                                if (typeof window != 'undefined')






                                share|improve this answer














                                share|improve this answer



                                share|improve this answer








                                edited Feb 18 at 7:34









                                Rohan Kumar

                                35.4k96193




                                35.4k96193










                                answered Jul 27 '17 at 9:41









                                RaptorRaptor

                                2,11422624




                                2,11422624








                                • 1





                                  Don't you need to inject PLATFORM_ID in the constructor and give this value as parameter in de isPlatformBrowser method?

                                  – PierreDuc
                                  Dec 18 '17 at 10:41






                                • 1





                                  @PierreDuc Yes, the answer is wrong. isPlatformBrowser is a function and will always be truthy. I've edited it now.

                                  – Lazar Ljubenović
                                  Jan 14 '18 at 19:30













                                • Thanks! It's correct now! Just verified the API: github.com/angular/angular/blob/…

                                  – Raptor
                                  Jan 15 '18 at 2:52














                                • 1





                                  Don't you need to inject PLATFORM_ID in the constructor and give this value as parameter in de isPlatformBrowser method?

                                  – PierreDuc
                                  Dec 18 '17 at 10:41






                                • 1





                                  @PierreDuc Yes, the answer is wrong. isPlatformBrowser is a function and will always be truthy. I've edited it now.

                                  – Lazar Ljubenović
                                  Jan 14 '18 at 19:30













                                • Thanks! It's correct now! Just verified the API: github.com/angular/angular/blob/…

                                  – Raptor
                                  Jan 15 '18 at 2:52








                                1




                                1





                                Don't you need to inject PLATFORM_ID in the constructor and give this value as parameter in de isPlatformBrowser method?

                                – PierreDuc
                                Dec 18 '17 at 10:41





                                Don't you need to inject PLATFORM_ID in the constructor and give this value as parameter in de isPlatformBrowser method?

                                – PierreDuc
                                Dec 18 '17 at 10:41




                                1




                                1





                                @PierreDuc Yes, the answer is wrong. isPlatformBrowser is a function and will always be truthy. I've edited it now.

                                – Lazar Ljubenović
                                Jan 14 '18 at 19:30







                                @PierreDuc Yes, the answer is wrong. isPlatformBrowser is a function and will always be truthy. I've edited it now.

                                – Lazar Ljubenović
                                Jan 14 '18 at 19:30















                                Thanks! It's correct now! Just verified the API: github.com/angular/angular/blob/…

                                – Raptor
                                Jan 15 '18 at 2:52





                                Thanks! It's correct now! Just verified the API: github.com/angular/angular/blob/…

                                – Raptor
                                Jan 15 '18 at 2:52











                                12














                                just do it easy with click action



                                in your main component html make reference #scrollContainer



                                <div class="main-container" #scrollContainer>
                                <router-outlet (activate)="onActivate($event, scrollContainer)"></router-outlet>
                                </div>


                                in main component .ts



                                onActivate(e, scrollContainer) {
                                scrollContainer.scrollTop = 0;
                                }





                                share|improve this answer


























                                • The element to be scrolled might not be in the scrollContainer first node, you might need to dig a bit in the object, for me what it really worked was scrollContainer .scrollable._elementRef.nativeElement.scrollTop = 0

                                  – Byron Lopez
                                  Mar 16 '18 at 22:19
















                                12














                                just do it easy with click action



                                in your main component html make reference #scrollContainer



                                <div class="main-container" #scrollContainer>
                                <router-outlet (activate)="onActivate($event, scrollContainer)"></router-outlet>
                                </div>


                                in main component .ts



                                onActivate(e, scrollContainer) {
                                scrollContainer.scrollTop = 0;
                                }





                                share|improve this answer


























                                • The element to be scrolled might not be in the scrollContainer first node, you might need to dig a bit in the object, for me what it really worked was scrollContainer .scrollable._elementRef.nativeElement.scrollTop = 0

                                  – Byron Lopez
                                  Mar 16 '18 at 22:19














                                12












                                12








                                12







                                just do it easy with click action



                                in your main component html make reference #scrollContainer



                                <div class="main-container" #scrollContainer>
                                <router-outlet (activate)="onActivate($event, scrollContainer)"></router-outlet>
                                </div>


                                in main component .ts



                                onActivate(e, scrollContainer) {
                                scrollContainer.scrollTop = 0;
                                }





                                share|improve this answer















                                just do it easy with click action



                                in your main component html make reference #scrollContainer



                                <div class="main-container" #scrollContainer>
                                <router-outlet (activate)="onActivate($event, scrollContainer)"></router-outlet>
                                </div>


                                in main component .ts



                                onActivate(e, scrollContainer) {
                                scrollContainer.scrollTop = 0;
                                }






                                share|improve this answer














                                share|improve this answer



                                share|improve this answer








                                edited Jun 13 '17 at 4:26









                                ScottMcGready

                                1,45321832




                                1,45321832










                                answered Jun 13 '17 at 2:38









                                SATSAT

                                11913




                                11913













                                • The element to be scrolled might not be in the scrollContainer first node, you might need to dig a bit in the object, for me what it really worked was scrollContainer .scrollable._elementRef.nativeElement.scrollTop = 0

                                  – Byron Lopez
                                  Mar 16 '18 at 22:19



















                                • The element to be scrolled might not be in the scrollContainer first node, you might need to dig a bit in the object, for me what it really worked was scrollContainer .scrollable._elementRef.nativeElement.scrollTop = 0

                                  – Byron Lopez
                                  Mar 16 '18 at 22:19

















                                The element to be scrolled might not be in the scrollContainer first node, you might need to dig a bit in the object, for me what it really worked was scrollContainer .scrollable._elementRef.nativeElement.scrollTop = 0

                                – Byron Lopez
                                Mar 16 '18 at 22:19





                                The element to be scrolled might not be in the scrollContainer first node, you might need to dig a bit in the object, for me what it really worked was scrollContainer .scrollable._elementRef.nativeElement.scrollTop = 0

                                – Byron Lopez
                                Mar 16 '18 at 22:19











                                10














                                The best answer resides in the Angular GitHub discussion (Changing route doesn't scroll to top in the new page).




                                Maybe you want go to top only in root router changes (not in children,
                                because you can load routes with lazy load in f.e. a tabset)




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


                                Full credits to JoniJnm (original post)






                                share|improve this answer






























                                  10














                                  The best answer resides in the Angular GitHub discussion (Changing route doesn't scroll to top in the new page).




                                  Maybe you want go to top only in root router changes (not in children,
                                  because you can load routes with lazy load in f.e. a tabset)




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


                                  Full credits to JoniJnm (original post)






                                  share|improve this answer




























                                    10












                                    10








                                    10







                                    The best answer resides in the Angular GitHub discussion (Changing route doesn't scroll to top in the new page).




                                    Maybe you want go to top only in root router changes (not in children,
                                    because you can load routes with lazy load in f.e. a tabset)




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


                                    Full credits to JoniJnm (original post)






                                    share|improve this answer















                                    The best answer resides in the Angular GitHub discussion (Changing route doesn't scroll to top in the new page).




                                    Maybe you want go to top only in root router changes (not in children,
                                    because you can load routes with lazy load in f.e. a tabset)




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


                                    Full credits to JoniJnm (original post)







                                    share|improve this answer














                                    share|improve this answer



                                    share|improve this answer








                                    edited Aug 25 '17 at 19:31

























                                    answered Aug 25 '17 at 19:22









                                    zurfyxzurfyx

                                    13.4k1076102




                                    13.4k1076102























                                        6














                                        You can add the AfterViewInit lifecycle hook to your component.



                                        ngAfterViewInit() {
                                        window.scrollTo(0, 0);
                                        }





                                        share|improve this answer




























                                          6














                                          You can add the AfterViewInit lifecycle hook to your component.



                                          ngAfterViewInit() {
                                          window.scrollTo(0, 0);
                                          }





                                          share|improve this answer


























                                            6












                                            6








                                            6







                                            You can add the AfterViewInit lifecycle hook to your component.



                                            ngAfterViewInit() {
                                            window.scrollTo(0, 0);
                                            }





                                            share|improve this answer













                                            You can add the AfterViewInit lifecycle hook to your component.



                                            ngAfterViewInit() {
                                            window.scrollTo(0, 0);
                                            }






                                            share|improve this answer












                                            share|improve this answer



                                            share|improve this answer










                                            answered Dec 2 '17 at 20:05









                                            stillatmylinuxstillatmylinux

                                            792718




                                            792718























                                                4














                                                Here's a solution that I've come up with. I paired up the LocationStrategy with the Router events. Using the LocationStrategy to set a boolean to know when a user's currently traversing through the browser history. This way, I don't have to store a bunch of URL and y-scroll data (which doesn't work well anyway, since each data is replaced based on URL). This also solves the edge case when a user decides to hold the back or forward button on a browser and goes back or forward multiple pages rather than just one.



                                                P.S. I've only tested on the latest version of IE, Chrome, FireFox, Safari, and Opera (as of this post).



                                                Hope this helps.



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





                                                share|improve this answer






























                                                  4














                                                  Here's a solution that I've come up with. I paired up the LocationStrategy with the Router events. Using the LocationStrategy to set a boolean to know when a user's currently traversing through the browser history. This way, I don't have to store a bunch of URL and y-scroll data (which doesn't work well anyway, since each data is replaced based on URL). This also solves the edge case when a user decides to hold the back or forward button on a browser and goes back or forward multiple pages rather than just one.



                                                  P.S. I've only tested on the latest version of IE, Chrome, FireFox, Safari, and Opera (as of this post).



                                                  Hope this helps.



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





                                                  share|improve this answer




























                                                    4












                                                    4








                                                    4







                                                    Here's a solution that I've come up with. I paired up the LocationStrategy with the Router events. Using the LocationStrategy to set a boolean to know when a user's currently traversing through the browser history. This way, I don't have to store a bunch of URL and y-scroll data (which doesn't work well anyway, since each data is replaced based on URL). This also solves the edge case when a user decides to hold the back or forward button on a browser and goes back or forward multiple pages rather than just one.



                                                    P.S. I've only tested on the latest version of IE, Chrome, FireFox, Safari, and Opera (as of this post).



                                                    Hope this helps.



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





                                                    share|improve this answer















                                                    Here's a solution that I've come up with. I paired up the LocationStrategy with the Router events. Using the LocationStrategy to set a boolean to know when a user's currently traversing through the browser history. This way, I don't have to store a bunch of URL and y-scroll data (which doesn't work well anyway, since each data is replaced based on URL). This also solves the edge case when a user decides to hold the back or forward button on a browser and goes back or forward multiple pages rather than just one.



                                                    P.S. I've only tested on the latest version of IE, Chrome, FireFox, Safari, and Opera (as of this post).



                                                    Hope this helps.



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






                                                    share|improve this answer














                                                    share|improve this answer



                                                    share|improve this answer








                                                    edited Apr 15 '18 at 6:39

























                                                    answered Mar 12 '18 at 10:48









                                                    Sal_Vader_808Sal_Vader_808

                                                    31529




                                                    31529























                                                        3














                                                        If you need simply scroll page to top, you can do this (not the best solution, but fast)



                                                        document.getElementById('elementId').scrollTop = 0;





                                                        share|improve this answer




























                                                          3














                                                          If you need simply scroll page to top, you can do this (not the best solution, but fast)



                                                          document.getElementById('elementId').scrollTop = 0;





                                                          share|improve this answer


























                                                            3












                                                            3








                                                            3







                                                            If you need simply scroll page to top, you can do this (not the best solution, but fast)



                                                            document.getElementById('elementId').scrollTop = 0;





                                                            share|improve this answer













                                                            If you need simply scroll page to top, you can do this (not the best solution, but fast)



                                                            document.getElementById('elementId').scrollTop = 0;






                                                            share|improve this answer












                                                            share|improve this answer



                                                            share|improve this answer










                                                            answered Sep 28 '17 at 17:15









                                                            AliakseiAliaksei

                                                            11518




                                                            11518























                                                                3














                                                                This solution is based on @FernandoEcheverria's and @GuilhermeMeireles's solution, but it is more concise and works with the popstate mechanisms that the Angular Router provides. This allows for storing and restoring the scroll level of multiple consecutive navigations.



                                                                We store the scroll positions for each navigation state in a map scrollLevels. Once there is a popstate event, the ID of the state that is about to be restored is supplied by the Angular Router: event.restoredState.navigationId. This is then used to get the last scroll level of that state from scrollLevels.



                                                                If there is no stored scroll level for the route, it will scroll to the top as you would expect.



                                                                import { Component, OnInit } from '@angular/core';
                                                                import { Router, NavigationStart, NavigationEnd } from '@angular/router';

                                                                @Component({
                                                                selector: 'my-app',
                                                                template: '<ng-content></ng-content>',
                                                                })
                                                                export class AppComponent implements OnInit {

                                                                constructor(private router: Router) { }

                                                                ngOnInit() {
                                                                const scrollLevels: { [navigationId: number]: number } = {};
                                                                let lastId = 0;
                                                                let restoredId: number;

                                                                this.router.events.subscribe((event: Event) => {

                                                                if (event instanceof NavigationStart) {
                                                                scrollLevels[lastId] = window.scrollY;
                                                                lastId = event.id;
                                                                restoredId = event.restoredState ? event.restoredState.navigationId : undefined;
                                                                }

                                                                if (event instanceof NavigationEnd) {
                                                                if (restoredId) {
                                                                // Optional: Wrap a timeout around the next line to wait for
                                                                // the component to finish loading
                                                                window.scrollTo(0, scrollLevels[restoredId] || 0);
                                                                } else {
                                                                window.scrollTo(0, 0);
                                                                }
                                                                }

                                                                });
                                                                }

                                                                }





                                                                share|improve this answer


























                                                                • Awesome. I had to make a slightly custom version to scroll a div rather than window, but it worked. One key difference was scrollTop vs scrollY.

                                                                  – BBaysinger
                                                                  Jul 18 '18 at 3:35
















                                                                3














                                                                This solution is based on @FernandoEcheverria's and @GuilhermeMeireles's solution, but it is more concise and works with the popstate mechanisms that the Angular Router provides. This allows for storing and restoring the scroll level of multiple consecutive navigations.



                                                                We store the scroll positions for each navigation state in a map scrollLevels. Once there is a popstate event, the ID of the state that is about to be restored is supplied by the Angular Router: event.restoredState.navigationId. This is then used to get the last scroll level of that state from scrollLevels.



                                                                If there is no stored scroll level for the route, it will scroll to the top as you would expect.



                                                                import { Component, OnInit } from '@angular/core';
                                                                import { Router, NavigationStart, NavigationEnd } from '@angular/router';

                                                                @Component({
                                                                selector: 'my-app',
                                                                template: '<ng-content></ng-content>',
                                                                })
                                                                export class AppComponent implements OnInit {

                                                                constructor(private router: Router) { }

                                                                ngOnInit() {
                                                                const scrollLevels: { [navigationId: number]: number } = {};
                                                                let lastId = 0;
                                                                let restoredId: number;

                                                                this.router.events.subscribe((event: Event) => {

                                                                if (event instanceof NavigationStart) {
                                                                scrollLevels[lastId] = window.scrollY;
                                                                lastId = event.id;
                                                                restoredId = event.restoredState ? event.restoredState.navigationId : undefined;
                                                                }

                                                                if (event instanceof NavigationEnd) {
                                                                if (restoredId) {
                                                                // Optional: Wrap a timeout around the next line to wait for
                                                                // the component to finish loading
                                                                window.scrollTo(0, scrollLevels[restoredId] || 0);
                                                                } else {
                                                                window.scrollTo(0, 0);
                                                                }
                                                                }

                                                                });
                                                                }

                                                                }





                                                                share|improve this answer


























                                                                • Awesome. I had to make a slightly custom version to scroll a div rather than window, but it worked. One key difference was scrollTop vs scrollY.

                                                                  – BBaysinger
                                                                  Jul 18 '18 at 3:35














                                                                3












                                                                3








                                                                3







                                                                This solution is based on @FernandoEcheverria's and @GuilhermeMeireles's solution, but it is more concise and works with the popstate mechanisms that the Angular Router provides. This allows for storing and restoring the scroll level of multiple consecutive navigations.



                                                                We store the scroll positions for each navigation state in a map scrollLevels. Once there is a popstate event, the ID of the state that is about to be restored is supplied by the Angular Router: event.restoredState.navigationId. This is then used to get the last scroll level of that state from scrollLevels.



                                                                If there is no stored scroll level for the route, it will scroll to the top as you would expect.



                                                                import { Component, OnInit } from '@angular/core';
                                                                import { Router, NavigationStart, NavigationEnd } from '@angular/router';

                                                                @Component({
                                                                selector: 'my-app',
                                                                template: '<ng-content></ng-content>',
                                                                })
                                                                export class AppComponent implements OnInit {

                                                                constructor(private router: Router) { }

                                                                ngOnInit() {
                                                                const scrollLevels: { [navigationId: number]: number } = {};
                                                                let lastId = 0;
                                                                let restoredId: number;

                                                                this.router.events.subscribe((event: Event) => {

                                                                if (event instanceof NavigationStart) {
                                                                scrollLevels[lastId] = window.scrollY;
                                                                lastId = event.id;
                                                                restoredId = event.restoredState ? event.restoredState.navigationId : undefined;
                                                                }

                                                                if (event instanceof NavigationEnd) {
                                                                if (restoredId) {
                                                                // Optional: Wrap a timeout around the next line to wait for
                                                                // the component to finish loading
                                                                window.scrollTo(0, scrollLevels[restoredId] || 0);
                                                                } else {
                                                                window.scrollTo(0, 0);
                                                                }
                                                                }

                                                                });
                                                                }

                                                                }





                                                                share|improve this answer















                                                                This solution is based on @FernandoEcheverria's and @GuilhermeMeireles's solution, but it is more concise and works with the popstate mechanisms that the Angular Router provides. This allows for storing and restoring the scroll level of multiple consecutive navigations.



                                                                We store the scroll positions for each navigation state in a map scrollLevels. Once there is a popstate event, the ID of the state that is about to be restored is supplied by the Angular Router: event.restoredState.navigationId. This is then used to get the last scroll level of that state from scrollLevels.



                                                                If there is no stored scroll level for the route, it will scroll to the top as you would expect.



                                                                import { Component, OnInit } from '@angular/core';
                                                                import { Router, NavigationStart, NavigationEnd } from '@angular/router';

                                                                @Component({
                                                                selector: 'my-app',
                                                                template: '<ng-content></ng-content>',
                                                                })
                                                                export class AppComponent implements OnInit {

                                                                constructor(private router: Router) { }

                                                                ngOnInit() {
                                                                const scrollLevels: { [navigationId: number]: number } = {};
                                                                let lastId = 0;
                                                                let restoredId: number;

                                                                this.router.events.subscribe((event: Event) => {

                                                                if (event instanceof NavigationStart) {
                                                                scrollLevels[lastId] = window.scrollY;
                                                                lastId = event.id;
                                                                restoredId = event.restoredState ? event.restoredState.navigationId : undefined;
                                                                }

                                                                if (event instanceof NavigationEnd) {
                                                                if (restoredId) {
                                                                // Optional: Wrap a timeout around the next line to wait for
                                                                // the component to finish loading
                                                                window.scrollTo(0, scrollLevels[restoredId] || 0);
                                                                } else {
                                                                window.scrollTo(0, 0);
                                                                }
                                                                }

                                                                });
                                                                }

                                                                }






                                                                share|improve this answer














                                                                share|improve this answer



                                                                share|improve this answer








                                                                edited Jul 10 '18 at 23:16

























                                                                answered Jul 10 '18 at 22:43









                                                                Simon MathewsonSimon Mathewson

                                                                503214




                                                                503214













                                                                • Awesome. I had to make a slightly custom version to scroll a div rather than window, but it worked. One key difference was scrollTop vs scrollY.

                                                                  – BBaysinger
                                                                  Jul 18 '18 at 3:35



















                                                                • Awesome. I had to make a slightly custom version to scroll a div rather than window, but it worked. One key difference was scrollTop vs scrollY.

                                                                  – BBaysinger
                                                                  Jul 18 '18 at 3:35

















                                                                Awesome. I had to make a slightly custom version to scroll a div rather than window, but it worked. One key difference was scrollTop vs scrollY.

                                                                – BBaysinger
                                                                Jul 18 '18 at 3:35





                                                                Awesome. I had to make a slightly custom version to scroll a div rather than window, but it worked. One key difference was scrollTop vs scrollY.

                                                                – BBaysinger
                                                                Jul 18 '18 at 3:35











                                                                3














                                                                As of Angular 6.1, the router provides a configuration option called scrollPositionRestoration, this is designed to cater for this scenario.



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





                                                                share|improve this answer




























                                                                  3














                                                                  As of Angular 6.1, the router provides a configuration option called scrollPositionRestoration, this is designed to cater for this scenario.



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





                                                                  share|improve this answer


























                                                                    3












                                                                    3








                                                                    3







                                                                    As of Angular 6.1, the router provides a configuration option called scrollPositionRestoration, this is designed to cater for this scenario.



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





                                                                    share|improve this answer













                                                                    As of Angular 6.1, the router provides a configuration option called scrollPositionRestoration, this is designed to cater for this scenario.



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






                                                                    share|improve this answer












                                                                    share|improve this answer



                                                                    share|improve this answer










                                                                    answered Sep 11 '18 at 23:32









                                                                    Marty AMarty A

                                                                    19316




                                                                    19316























                                                                        1














                                                                        for iphone/ios safari you can wrap with a setTimeout



                                                                        setTimeout(function(){
                                                                        window.scrollTo(0, 1);
                                                                        }, 0);





                                                                        share|improve this answer


























                                                                        • in my case it also required the page wrapping element css to be set to; height: 100vh + 1px;

                                                                          – tubbsy
                                                                          Mar 10 '17 at 17:52


















                                                                        1














                                                                        for iphone/ios safari you can wrap with a setTimeout



                                                                        setTimeout(function(){
                                                                        window.scrollTo(0, 1);
                                                                        }, 0);





                                                                        share|improve this answer


























                                                                        • in my case it also required the page wrapping element css to be set to; height: 100vh + 1px;

                                                                          – tubbsy
                                                                          Mar 10 '17 at 17:52
















                                                                        1












                                                                        1








                                                                        1







                                                                        for iphone/ios safari you can wrap with a setTimeout



                                                                        setTimeout(function(){
                                                                        window.scrollTo(0, 1);
                                                                        }, 0);





                                                                        share|improve this answer















                                                                        for iphone/ios safari you can wrap with a setTimeout



                                                                        setTimeout(function(){
                                                                        window.scrollTo(0, 1);
                                                                        }, 0);






                                                                        share|improve this answer














                                                                        share|improve this answer



                                                                        share|improve this answer








                                                                        edited Mar 8 '17 at 12:46

























                                                                        answered Mar 8 '17 at 12:15









                                                                        tubbsytubbsy

                                                                        416




                                                                        416













                                                                        • in my case it also required the page wrapping element css to be set to; height: 100vh + 1px;

                                                                          – tubbsy
                                                                          Mar 10 '17 at 17:52





















                                                                        • in my case it also required the page wrapping element css to be set to; height: 100vh + 1px;

                                                                          – tubbsy
                                                                          Mar 10 '17 at 17:52



















                                                                        in my case it also required the page wrapping element css to be set to; height: 100vh + 1px;

                                                                        – tubbsy
                                                                        Mar 10 '17 at 17:52







                                                                        in my case it also required the page wrapping element css to be set to; height: 100vh + 1px;

                                                                        – tubbsy
                                                                        Mar 10 '17 at 17:52













                                                                        1














                                                                        Hi guys this works for me in angular 4. You just have to reference the parent to scroll on router change`



                                                                        layout.component.pug



                                                                        .wrapper(#outlet="")
                                                                        router-outlet((activate)='routerActivate($event,outlet)')


                                                                        layout.component.ts



                                                                         public routerActivate(event,outlet){
                                                                        outlet.scrollTop = 0;
                                                                        }`





                                                                        share|improve this answer



















                                                                        • 1





                                                                          pardon my laziness in not bothering to learn pug, but can you translate to HTML?

                                                                          – CodyBugstein
                                                                          Feb 9 '18 at 16:47
















                                                                        1














                                                                        Hi guys this works for me in angular 4. You just have to reference the parent to scroll on router change`



                                                                        layout.component.pug



                                                                        .wrapper(#outlet="")
                                                                        router-outlet((activate)='routerActivate($event,outlet)')


                                                                        layout.component.ts



                                                                         public routerActivate(event,outlet){
                                                                        outlet.scrollTop = 0;
                                                                        }`





                                                                        share|improve this answer



















                                                                        • 1





                                                                          pardon my laziness in not bothering to learn pug, but can you translate to HTML?

                                                                          – CodyBugstein
                                                                          Feb 9 '18 at 16:47














                                                                        1












                                                                        1








                                                                        1







                                                                        Hi guys this works for me in angular 4. You just have to reference the parent to scroll on router change`



                                                                        layout.component.pug



                                                                        .wrapper(#outlet="")
                                                                        router-outlet((activate)='routerActivate($event,outlet)')


                                                                        layout.component.ts



                                                                         public routerActivate(event,outlet){
                                                                        outlet.scrollTop = 0;
                                                                        }`





                                                                        share|improve this answer













                                                                        Hi guys this works for me in angular 4. You just have to reference the parent to scroll on router change`



                                                                        layout.component.pug



                                                                        .wrapper(#outlet="")
                                                                        router-outlet((activate)='routerActivate($event,outlet)')


                                                                        layout.component.ts



                                                                         public routerActivate(event,outlet){
                                                                        outlet.scrollTop = 0;
                                                                        }`






                                                                        share|improve this answer












                                                                        share|improve this answer



                                                                        share|improve this answer










                                                                        answered Jan 5 '18 at 9:49









                                                                        Jonas ArguellesJonas Arguelles

                                                                        1111




                                                                        1111








                                                                        • 1





                                                                          pardon my laziness in not bothering to learn pug, but can you translate to HTML?

                                                                          – CodyBugstein
                                                                          Feb 9 '18 at 16:47














                                                                        • 1





                                                                          pardon my laziness in not bothering to learn pug, but can you translate to HTML?

                                                                          – CodyBugstein
                                                                          Feb 9 '18 at 16:47








                                                                        1




                                                                        1





                                                                        pardon my laziness in not bothering to learn pug, but can you translate to HTML?

                                                                        – CodyBugstein
                                                                        Feb 9 '18 at 16:47





                                                                        pardon my laziness in not bothering to learn pug, but can you translate to HTML?

                                                                        – CodyBugstein
                                                                        Feb 9 '18 at 16:47











                                                                        0














                                                                        @Fernando Echeverria
                                                                        great! but this code not work in hash router or lazy router. because they do not trigger location changes.
                                                                        can try this:






                                                                        private lastRouteUrl: string = 


                                                                        ngOnInit(): void {
                                                                        this.router.events.subscribe((ev) => {
                                                                        const len = this.lastRouteUrl.length
                                                                        if (ev instanceof NavigationEnd) {
                                                                        this.lastRouteUrl.push(ev.url)
                                                                        if (len > 1 && ev.url === this.lastRouteUrl[len - 2]) {
                                                                        return
                                                                        }
                                                                        window.scrollTo(0, 0)
                                                                        }
                                                                        })
                                                                        }








                                                                        share|improve this answer




























                                                                          0














                                                                          @Fernando Echeverria
                                                                          great! but this code not work in hash router or lazy router. because they do not trigger location changes.
                                                                          can try this:






                                                                          private lastRouteUrl: string = 


                                                                          ngOnInit(): void {
                                                                          this.router.events.subscribe((ev) => {
                                                                          const len = this.lastRouteUrl.length
                                                                          if (ev instanceof NavigationEnd) {
                                                                          this.lastRouteUrl.push(ev.url)
                                                                          if (len > 1 && ev.url === this.lastRouteUrl[len - 2]) {
                                                                          return
                                                                          }
                                                                          window.scrollTo(0, 0)
                                                                          }
                                                                          })
                                                                          }








                                                                          share|improve this answer


























                                                                            0












                                                                            0








                                                                            0







                                                                            @Fernando Echeverria
                                                                            great! but this code not work in hash router or lazy router. because they do not trigger location changes.
                                                                            can try this:






                                                                            private lastRouteUrl: string = 


                                                                            ngOnInit(): void {
                                                                            this.router.events.subscribe((ev) => {
                                                                            const len = this.lastRouteUrl.length
                                                                            if (ev instanceof NavigationEnd) {
                                                                            this.lastRouteUrl.push(ev.url)
                                                                            if (len > 1 && ev.url === this.lastRouteUrl[len - 2]) {
                                                                            return
                                                                            }
                                                                            window.scrollTo(0, 0)
                                                                            }
                                                                            })
                                                                            }








                                                                            share|improve this answer













                                                                            @Fernando Echeverria
                                                                            great! but this code not work in hash router or lazy router. because they do not trigger location changes.
                                                                            can try this:






                                                                            private lastRouteUrl: string = 


                                                                            ngOnInit(): void {
                                                                            this.router.events.subscribe((ev) => {
                                                                            const len = this.lastRouteUrl.length
                                                                            if (ev instanceof NavigationEnd) {
                                                                            this.lastRouteUrl.push(ev.url)
                                                                            if (len > 1 && ev.url === this.lastRouteUrl[len - 2]) {
                                                                            return
                                                                            }
                                                                            window.scrollTo(0, 0)
                                                                            }
                                                                            })
                                                                            }








                                                                            private lastRouteUrl: string = 


                                                                            ngOnInit(): void {
                                                                            this.router.events.subscribe((ev) => {
                                                                            const len = this.lastRouteUrl.length
                                                                            if (ev instanceof NavigationEnd) {
                                                                            this.lastRouteUrl.push(ev.url)
                                                                            if (len > 1 && ev.url === this.lastRouteUrl[len - 2]) {
                                                                            return
                                                                            }
                                                                            window.scrollTo(0, 0)
                                                                            }
                                                                            })
                                                                            }





                                                                            private lastRouteUrl: string = 


                                                                            ngOnInit(): void {
                                                                            this.router.events.subscribe((ev) => {
                                                                            const len = this.lastRouteUrl.length
                                                                            if (ev instanceof NavigationEnd) {
                                                                            this.lastRouteUrl.push(ev.url)
                                                                            if (len > 1 && ev.url === this.lastRouteUrl[len - 2]) {
                                                                            return
                                                                            }
                                                                            window.scrollTo(0, 0)
                                                                            }
                                                                            })
                                                                            }






                                                                            share|improve this answer












                                                                            share|improve this answer



                                                                            share|improve this answer










                                                                            answered Sep 1 '17 at 18:42









                                                                            Witt BulterWitt Bulter

                                                                            12




                                                                            12























                                                                                0














                                                                                Using the Router itself will cause issues which you cannot completely overcome to maintain consistent browser experience. In my opinion the best method is to just use a custom directive and let this reset the scroll on click. The good thing about this, is that if you are on the same url as that you click on, the page will scroll back to the top as well. This is consistent with normal websites. The basic directive could look something like this:



                                                                                import {Directive, HostListener} from '@angular/core';

                                                                                @Directive({
                                                                                selector: '[linkToTop]'
                                                                                })
                                                                                export class LinkToTopDirective {

                                                                                @HostListener('click')
                                                                                onClick(): void {
                                                                                window.scrollTo(0, 0);
                                                                                }
                                                                                }


                                                                                With the following usage:



                                                                                <a routerLink="/" linkToTop></a>


                                                                                This will be enough for most use-cases, but I can imagine a few issues which may
                                                                                arise from this:




                                                                                • Doesn't work on universal because of the usage of window

                                                                                • Small speed impact on change detection, because it is triggered by every click

                                                                                • No way to disable this directive


                                                                                It is actually quite easy to overcome these issues:



                                                                                @Directive({
                                                                                selector: '[linkToTop]'
                                                                                })
                                                                                export class LinkToTopDirective implements OnInit, OnDestroy {

                                                                                @Input()
                                                                                set linkToTop(active: string | boolean) {
                                                                                this.active = typeof active === 'string' ? active.length === 0 : active;
                                                                                }

                                                                                private active: boolean = true;

                                                                                private onClick: EventListener = (event: MouseEvent) => {
                                                                                if (this.active) {
                                                                                window.scrollTo(0, 0);
                                                                                }
                                                                                };

                                                                                constructor(@Inject(PLATFORM_ID) private readonly platformId: Object,
                                                                                private readonly elementRef: ElementRef,
                                                                                private readonly ngZone: NgZone
                                                                                ) {}

                                                                                ngOnDestroy(): void {
                                                                                if (isPlatformBrowser(this.platformId)) {
                                                                                this.elementRef.nativeElement.removeEventListener('click', this.onClick, false);
                                                                                }
                                                                                }

                                                                                ngOnInit(): void {
                                                                                if (isPlatformBrowser(this.platformId)) {
                                                                                this.ngZone.runOutsideAngular(() =>
                                                                                this.elementRef.nativeElement.addEventListener('click', this.onClick, false)
                                                                                );
                                                                                }
                                                                                }
                                                                                }


                                                                                This takes most use-cases into account, with the same usage as the basic one, with the advantage of enable/disabling it:



                                                                                <a routerLink="/" linkToTop></a> <!-- always active -->
                                                                                <a routerLink="/" [linkToTop]="isActive"> <!-- active when `isActive` is true -->


                                                                                commercials, don't read if you don't want to be advertised



                                                                                Another improvement could be made to check whether or not the browser supports passive events. This will complicate the code a bit more, and is a bit obscure if you want to implement all these in your custom directives/templates. That's why I wrote a little library which you can use to address these problems. To have the same functionality as above, and with the added passive event, you can change your directive to this, if you use the ng-event-options library. The logic is inside the click.pnb listener:



                                                                                @Directive({
                                                                                selector: '[linkToTop]'
                                                                                })
                                                                                export class LinkToTopDirective {

                                                                                @Input()
                                                                                set linkToTop(active: string|boolean) {
                                                                                this.active = typeof active === 'string' ? active.length === 0 : active;
                                                                                }

                                                                                private active: boolean = true;

                                                                                @HostListener('click.pnb')
                                                                                onClick(): void {
                                                                                if (this.active) {
                                                                                window.scrollTo(0, 0);
                                                                                }
                                                                                }
                                                                                }





                                                                                share|improve this answer






























                                                                                  0














                                                                                  Using the Router itself will cause issues which you cannot completely overcome to maintain consistent browser experience. In my opinion the best method is to just use a custom directive and let this reset the scroll on click. The good thing about this, is that if you are on the same url as that you click on, the page will scroll back to the top as well. This is consistent with normal websites. The basic directive could look something like this:



                                                                                  import {Directive, HostListener} from '@angular/core';

                                                                                  @Directive({
                                                                                  selector: '[linkToTop]'
                                                                                  })
                                                                                  export class LinkToTopDirective {

                                                                                  @HostListener('click')
                                                                                  onClick(): void {
                                                                                  window.scrollTo(0, 0);
                                                                                  }
                                                                                  }


                                                                                  With the following usage:



                                                                                  <a routerLink="/" linkToTop></a>


                                                                                  This will be enough for most use-cases, but I can imagine a few issues which may
                                                                                  arise from this:




                                                                                  • Doesn't work on universal because of the usage of window

                                                                                  • Small speed impact on change detection, because it is triggered by every click

                                                                                  • No way to disable this directive


                                                                                  It is actually quite easy to overcome these issues:



                                                                                  @Directive({
                                                                                  selector: '[linkToTop]'
                                                                                  })
                                                                                  export class LinkToTopDirective implements OnInit, OnDestroy {

                                                                                  @Input()
                                                                                  set linkToTop(active: string | boolean) {
                                                                                  this.active = typeof active === 'string' ? active.length === 0 : active;
                                                                                  }

                                                                                  private active: boolean = true;

                                                                                  private onClick: EventListener = (event: MouseEvent) => {
                                                                                  if (this.active) {
                                                                                  window.scrollTo(0, 0);
                                                                                  }
                                                                                  };

                                                                                  constructor(@Inject(PLATFORM_ID) private readonly platformId: Object,
                                                                                  private readonly elementRef: ElementRef,
                                                                                  private readonly ngZone: NgZone
                                                                                  ) {}

                                                                                  ngOnDestroy(): void {
                                                                                  if (isPlatformBrowser(this.platformId)) {
                                                                                  this.elementRef.nativeElement.removeEventListener('click', this.onClick, false);
                                                                                  }
                                                                                  }

                                                                                  ngOnInit(): void {
                                                                                  if (isPlatformBrowser(this.platformId)) {
                                                                                  this.ngZone.runOutsideAngular(() =>
                                                                                  this.elementRef.nativeElement.addEventListener('click', this.onClick, false)
                                                                                  );
                                                                                  }
                                                                                  }
                                                                                  }


                                                                                  This takes most use-cases into account, with the same usage as the basic one, with the advantage of enable/disabling it:



                                                                                  <a routerLink="/" linkToTop></a> <!-- always active -->
                                                                                  <a routerLink="/" [linkToTop]="isActive"> <!-- active when `isActive` is true -->


                                                                                  commercials, don't read if you don't want to be advertised



                                                                                  Another improvement could be made to check whether or not the browser supports passive events. This will complicate the code a bit more, and is a bit obscure if you want to implement all these in your custom directives/templates. That's why I wrote a little library which you can use to address these problems. To have the same functionality as above, and with the added passive event, you can change your directive to this, if you use the ng-event-options library. The logic is inside the click.pnb listener:



                                                                                  @Directive({
                                                                                  selector: '[linkToTop]'
                                                                                  })
                                                                                  export class LinkToTopDirective {

                                                                                  @Input()
                                                                                  set linkToTop(active: string|boolean) {
                                                                                  this.active = typeof active === 'string' ? active.length === 0 : active;
                                                                                  }

                                                                                  private active: boolean = true;

                                                                                  @HostListener('click.pnb')
                                                                                  onClick(): void {
                                                                                  if (this.active) {
                                                                                  window.scrollTo(0, 0);
                                                                                  }
                                                                                  }
                                                                                  }





                                                                                  share|improve this answer




























                                                                                    0












                                                                                    0








                                                                                    0







                                                                                    Using the Router itself will cause issues which you cannot completely overcome to maintain consistent browser experience. In my opinion the best method is to just use a custom directive and let this reset the scroll on click. The good thing about this, is that if you are on the same url as that you click on, the page will scroll back to the top as well. This is consistent with normal websites. The basic directive could look something like this:



                                                                                    import {Directive, HostListener} from '@angular/core';

                                                                                    @Directive({
                                                                                    selector: '[linkToTop]'
                                                                                    })
                                                                                    export class LinkToTopDirective {

                                                                                    @HostListener('click')
                                                                                    onClick(): void {
                                                                                    window.scrollTo(0, 0);
                                                                                    }
                                                                                    }


                                                                                    With the following usage:



                                                                                    <a routerLink="/" linkToTop></a>


                                                                                    This will be enough for most use-cases, but I can imagine a few issues which may
                                                                                    arise from this:




                                                                                    • Doesn't work on universal because of the usage of window

                                                                                    • Small speed impact on change detection, because it is triggered by every click

                                                                                    • No way to disable this directive


                                                                                    It is actually quite easy to overcome these issues:



                                                                                    @Directive({
                                                                                    selector: '[linkToTop]'
                                                                                    })
                                                                                    export class LinkToTopDirective implements OnInit, OnDestroy {

                                                                                    @Input()
                                                                                    set linkToTop(active: string | boolean) {
                                                                                    this.active = typeof active === 'string' ? active.length === 0 : active;
                                                                                    }

                                                                                    private active: boolean = true;

                                                                                    private onClick: EventListener = (event: MouseEvent) => {
                                                                                    if (this.active) {
                                                                                    window.scrollTo(0, 0);
                                                                                    }
                                                                                    };

                                                                                    constructor(@Inject(PLATFORM_ID) private readonly platformId: Object,
                                                                                    private readonly elementRef: ElementRef,
                                                                                    private readonly ngZone: NgZone
                                                                                    ) {}

                                                                                    ngOnDestroy(): void {
                                                                                    if (isPlatformBrowser(this.platformId)) {
                                                                                    this.elementRef.nativeElement.removeEventListener('click', this.onClick, false);
                                                                                    }
                                                                                    }

                                                                                    ngOnInit(): void {
                                                                                    if (isPlatformBrowser(this.platformId)) {
                                                                                    this.ngZone.runOutsideAngular(() =>
                                                                                    this.elementRef.nativeElement.addEventListener('click', this.onClick, false)
                                                                                    );
                                                                                    }
                                                                                    }
                                                                                    }


                                                                                    This takes most use-cases into account, with the same usage as the basic one, with the advantage of enable/disabling it:



                                                                                    <a routerLink="/" linkToTop></a> <!-- always active -->
                                                                                    <a routerLink="/" [linkToTop]="isActive"> <!-- active when `isActive` is true -->


                                                                                    commercials, don't read if you don't want to be advertised



                                                                                    Another improvement could be made to check whether or not the browser supports passive events. This will complicate the code a bit more, and is a bit obscure if you want to implement all these in your custom directives/templates. That's why I wrote a little library which you can use to address these problems. To have the same functionality as above, and with the added passive event, you can change your directive to this, if you use the ng-event-options library. The logic is inside the click.pnb listener:



                                                                                    @Directive({
                                                                                    selector: '[linkToTop]'
                                                                                    })
                                                                                    export class LinkToTopDirective {

                                                                                    @Input()
                                                                                    set linkToTop(active: string|boolean) {
                                                                                    this.active = typeof active === 'string' ? active.length === 0 : active;
                                                                                    }

                                                                                    private active: boolean = true;

                                                                                    @HostListener('click.pnb')
                                                                                    onClick(): void {
                                                                                    if (this.active) {
                                                                                    window.scrollTo(0, 0);
                                                                                    }
                                                                                    }
                                                                                    }





                                                                                    share|improve this answer















                                                                                    Using the Router itself will cause issues which you cannot completely overcome to maintain consistent browser experience. In my opinion the best method is to just use a custom directive and let this reset the scroll on click. The good thing about this, is that if you are on the same url as that you click on, the page will scroll back to the top as well. This is consistent with normal websites. The basic directive could look something like this:



                                                                                    import {Directive, HostListener} from '@angular/core';

                                                                                    @Directive({
                                                                                    selector: '[linkToTop]'
                                                                                    })
                                                                                    export class LinkToTopDirective {

                                                                                    @HostListener('click')
                                                                                    onClick(): void {
                                                                                    window.scrollTo(0, 0);
                                                                                    }
                                                                                    }


                                                                                    With the following usage:



                                                                                    <a routerLink="/" linkToTop></a>


                                                                                    This will be enough for most use-cases, but I can imagine a few issues which may
                                                                                    arise from this:




                                                                                    • Doesn't work on universal because of the usage of window

                                                                                    • Small speed impact on change detection, because it is triggered by every click

                                                                                    • No way to disable this directive


                                                                                    It is actually quite easy to overcome these issues:



                                                                                    @Directive({
                                                                                    selector: '[linkToTop]'
                                                                                    })
                                                                                    export class LinkToTopDirective implements OnInit, OnDestroy {

                                                                                    @Input()
                                                                                    set linkToTop(active: string | boolean) {
                                                                                    this.active = typeof active === 'string' ? active.length === 0 : active;
                                                                                    }

                                                                                    private active: boolean = true;

                                                                                    private onClick: EventListener = (event: MouseEvent) => {
                                                                                    if (this.active) {
                                                                                    window.scrollTo(0, 0);
                                                                                    }
                                                                                    };

                                                                                    constructor(@Inject(PLATFORM_ID) private readonly platformId: Object,
                                                                                    private readonly elementRef: ElementRef,
                                                                                    private readonly ngZone: NgZone
                                                                                    ) {}

                                                                                    ngOnDestroy(): void {
                                                                                    if (isPlatformBrowser(this.platformId)) {
                                                                                    this.elementRef.nativeElement.removeEventListener('click', this.onClick, false);
                                                                                    }
                                                                                    }

                                                                                    ngOnInit(): void {
                                                                                    if (isPlatformBrowser(this.platformId)) {
                                                                                    this.ngZone.runOutsideAngular(() =>
                                                                                    this.elementRef.nativeElement.addEventListener('click', this.onClick, false)
                                                                                    );
                                                                                    }
                                                                                    }
                                                                                    }


                                                                                    This takes most use-cases into account, with the same usage as the basic one, with the advantage of enable/disabling it:



                                                                                    <a routerLink="/" linkToTop></a> <!-- always active -->
                                                                                    <a routerLink="/" [linkToTop]="isActive"> <!-- active when `isActive` is true -->


                                                                                    commercials, don't read if you don't want to be advertised



                                                                                    Another improvement could be made to check whether or not the browser supports passive events. This will complicate the code a bit more, and is a bit obscure if you want to implement all these in your custom directives/templates. That's why I wrote a little library which you can use to address these problems. To have the same functionality as above, and with the added passive event, you can change your directive to this, if you use the ng-event-options library. The logic is inside the click.pnb listener:



                                                                                    @Directive({
                                                                                    selector: '[linkToTop]'
                                                                                    })
                                                                                    export class LinkToTopDirective {

                                                                                    @Input()
                                                                                    set linkToTop(active: string|boolean) {
                                                                                    this.active = typeof active === 'string' ? active.length === 0 : active;
                                                                                    }

                                                                                    private active: boolean = true;

                                                                                    @HostListener('click.pnb')
                                                                                    onClick(): void {
                                                                                    if (this.active) {
                                                                                    window.scrollTo(0, 0);
                                                                                    }
                                                                                    }
                                                                                    }






                                                                                    share|improve this answer














                                                                                    share|improve this answer



                                                                                    share|improve this answer








                                                                                    edited Dec 18 '17 at 11:05

























                                                                                    answered Dec 18 '17 at 10:40









                                                                                    PierreDucPierreDuc

                                                                                    31.4k56280




                                                                                    31.4k56280























                                                                                        0














                                                                                        This worked for me best for all navigation changes including hash navigation



                                                                                        constructor(private route: ActivatedRoute) {}

                                                                                        ngOnInit() {
                                                                                        this._sub = this.route.fragment.subscribe((hash: string) => {
                                                                                        if (hash) {
                                                                                        const cmp = document.getElementById(hash);
                                                                                        if (cmp) {
                                                                                        cmp.scrollIntoView();
                                                                                        }
                                                                                        } else {
                                                                                        window.scrollTo(0, 0);
                                                                                        }
                                                                                        });
                                                                                        }







                                                                                        share|improve this answer




























                                                                                          0














                                                                                          This worked for me best for all navigation changes including hash navigation



                                                                                          constructor(private route: ActivatedRoute) {}

                                                                                          ngOnInit() {
                                                                                          this._sub = this.route.fragment.subscribe((hash: string) => {
                                                                                          if (hash) {
                                                                                          const cmp = document.getElementById(hash);
                                                                                          if (cmp) {
                                                                                          cmp.scrollIntoView();
                                                                                          }
                                                                                          } else {
                                                                                          window.scrollTo(0, 0);
                                                                                          }
                                                                                          });
                                                                                          }







                                                                                          share|improve this answer


























                                                                                            0












                                                                                            0








                                                                                            0







                                                                                            This worked for me best for all navigation changes including hash navigation



                                                                                            constructor(private route: ActivatedRoute) {}

                                                                                            ngOnInit() {
                                                                                            this._sub = this.route.fragment.subscribe((hash: string) => {
                                                                                            if (hash) {
                                                                                            const cmp = document.getElementById(hash);
                                                                                            if (cmp) {
                                                                                            cmp.scrollIntoView();
                                                                                            }
                                                                                            } else {
                                                                                            window.scrollTo(0, 0);
                                                                                            }
                                                                                            });
                                                                                            }







                                                                                            share|improve this answer













                                                                                            This worked for me best for all navigation changes including hash navigation



                                                                                            constructor(private route: ActivatedRoute) {}

                                                                                            ngOnInit() {
                                                                                            this._sub = this.route.fragment.subscribe((hash: string) => {
                                                                                            if (hash) {
                                                                                            const cmp = document.getElementById(hash);
                                                                                            if (cmp) {
                                                                                            cmp.scrollIntoView();
                                                                                            }
                                                                                            } else {
                                                                                            window.scrollTo(0, 0);
                                                                                            }
                                                                                            });
                                                                                            }








                                                                                            share|improve this answer












                                                                                            share|improve this answer



                                                                                            share|improve this answer










                                                                                            answered Jan 24 '18 at 20:10









                                                                                            Jorg JankeJorg Janke

                                                                                            47748




                                                                                            47748























                                                                                                0














                                                                                                The main idea behind this code is to keep all visited urls along with respective scrollY data in an array. Every time a user abandons a page (NavigationStart) this array is updated. Every time a user enters a new page (NavigationEnd), we decide to restore Y position or don't depending on how do we get to this page. If a refernce on some page was used we scroll to 0. If browser back/forward features were used we scroll to Y saved in our array. Sorry for my English :)



                                                                                                import { Component, OnInit, OnDestroy } from '@angular/core';
                                                                                                import { Location, PopStateEvent } from '@angular/common';
                                                                                                import { Router, Route, RouterLink, NavigationStart, NavigationEnd,
                                                                                                RouterEvent } from '@angular/router';
                                                                                                import { Subscription } from 'rxjs/Subscription';

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

                                                                                                private _subscription: Subscription;
                                                                                                private _scrollHistory: { url: string, y: number } = ;
                                                                                                private _useHistory = false;

                                                                                                constructor(
                                                                                                private _router: Router,
                                                                                                private _location: Location) {
                                                                                                }

                                                                                                public ngOnInit() {

                                                                                                this._subscription = this._router.events.subscribe((event: any) =>
                                                                                                {
                                                                                                if (event instanceof NavigationStart) {
                                                                                                const currentUrl = (this._location.path() !== '')
                                                                                                this._location.path() : '/';
                                                                                                const item = this._scrollHistory.find(x => x.url === currentUrl);
                                                                                                if (item) {
                                                                                                item.y = window.scrollY;
                                                                                                } else {
                                                                                                this._scrollHistory.push({ url: currentUrl, y: window.scrollY });
                                                                                                }
                                                                                                return;
                                                                                                }
                                                                                                if (event instanceof NavigationEnd) {
                                                                                                if (this._useHistory) {
                                                                                                this._useHistory = false;
                                                                                                window.scrollTo(0, this._scrollHistory.find(x => x.url ===
                                                                                                event.url).y);
                                                                                                } else {
                                                                                                window.scrollTo(0, 0);
                                                                                                }
                                                                                                }
                                                                                                });

                                                                                                this._subscription.add(this._location.subscribe((event: PopStateEvent)
                                                                                                => { this._useHistory = true;
                                                                                                }));
                                                                                                }

                                                                                                public ngOnDestroy(): void {
                                                                                                this._subscription.unsubscribe();
                                                                                                }
                                                                                                }





                                                                                                share|improve this answer




























                                                                                                  0














                                                                                                  The main idea behind this code is to keep all visited urls along with respective scrollY data in an array. Every time a user abandons a page (NavigationStart) this array is updated. Every time a user enters a new page (NavigationEnd), we decide to restore Y position or don't depending on how do we get to this page. If a refernce on some page was used we scroll to 0. If browser back/forward features were used we scroll to Y saved in our array. Sorry for my English :)



                                                                                                  import { Component, OnInit, OnDestroy } from '@angular/core';
                                                                                                  import { Location, PopStateEvent } from '@angular/common';
                                                                                                  import { Router, Route, RouterLink, NavigationStart, NavigationEnd,
                                                                                                  RouterEvent } from '@angular/router';
                                                                                                  import { Subscription } from 'rxjs/Subscription';

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

                                                                                                  private _subscription: Subscription;
                                                                                                  private _scrollHistory: { url: string, y: number } = ;
                                                                                                  private _useHistory = false;

                                                                                                  constructor(
                                                                                                  private _router: Router,
                                                                                                  private _location: Location) {
                                                                                                  }

                                                                                                  public ngOnInit() {

                                                                                                  this._subscription = this._router.events.subscribe((event: any) =>
                                                                                                  {
                                                                                                  if (event instanceof NavigationStart) {
                                                                                                  const currentUrl = (this._location.path() !== '')
                                                                                                  this._location.path() : '/';
                                                                                                  const item = this._scrollHistory.find(x => x.url === currentUrl);
                                                                                                  if (item) {
                                                                                                  item.y = window.scrollY;
                                                                                                  } else {
                                                                                                  this._scrollHistory.push({ url: currentUrl, y: window.scrollY });
                                                                                                  }
                                                                                                  return;
                                                                                                  }
                                                                                                  if (event instanceof NavigationEnd) {
                                                                                                  if (this._useHistory) {
                                                                                                  this._useHistory = false;
                                                                                                  window.scrollTo(0, this._scrollHistory.find(x => x.url ===
                                                                                                  event.url).y);
                                                                                                  } else {
                                                                                                  window.scrollTo(0, 0);
                                                                                                  }
                                                                                                  }
                                                                                                  });

                                                                                                  this._subscription.add(this._location.subscribe((event: PopStateEvent)
                                                                                                  => { this._useHistory = true;
                                                                                                  }));
                                                                                                  }

                                                                                                  public ngOnDestroy(): void {
                                                                                                  this._subscription.unsubscribe();
                                                                                                  }
                                                                                                  }





                                                                                                  share|improve this answer


























                                                                                                    0












                                                                                                    0








                                                                                                    0







                                                                                                    The main idea behind this code is to keep all visited urls along with respective scrollY data in an array. Every time a user abandons a page (NavigationStart) this array is updated. Every time a user enters a new page (NavigationEnd), we decide to restore Y position or don't depending on how do we get to this page. If a refernce on some page was used we scroll to 0. If browser back/forward features were used we scroll to Y saved in our array. Sorry for my English :)



                                                                                                    import { Component, OnInit, OnDestroy } from '@angular/core';
                                                                                                    import { Location, PopStateEvent } from '@angular/common';
                                                                                                    import { Router, Route, RouterLink, NavigationStart, NavigationEnd,
                                                                                                    RouterEvent } from '@angular/router';
                                                                                                    import { Subscription } from 'rxjs/Subscription';

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

                                                                                                    private _subscription: Subscription;
                                                                                                    private _scrollHistory: { url: string, y: number } = ;
                                                                                                    private _useHistory = false;

                                                                                                    constructor(
                                                                                                    private _router: Router,
                                                                                                    private _location: Location) {
                                                                                                    }

                                                                                                    public ngOnInit() {

                                                                                                    this._subscription = this._router.events.subscribe((event: any) =>
                                                                                                    {
                                                                                                    if (event instanceof NavigationStart) {
                                                                                                    const currentUrl = (this._location.path() !== '')
                                                                                                    this._location.path() : '/';
                                                                                                    const item = this._scrollHistory.find(x => x.url === currentUrl);
                                                                                                    if (item) {
                                                                                                    item.y = window.scrollY;
                                                                                                    } else {
                                                                                                    this._scrollHistory.push({ url: currentUrl, y: window.scrollY });
                                                                                                    }
                                                                                                    return;
                                                                                                    }
                                                                                                    if (event instanceof NavigationEnd) {
                                                                                                    if (this._useHistory) {
                                                                                                    this._useHistory = false;
                                                                                                    window.scrollTo(0, this._scrollHistory.find(x => x.url ===
                                                                                                    event.url).y);
                                                                                                    } else {
                                                                                                    window.scrollTo(0, 0);
                                                                                                    }
                                                                                                    }
                                                                                                    });

                                                                                                    this._subscription.add(this._location.subscribe((event: PopStateEvent)
                                                                                                    => { this._useHistory = true;
                                                                                                    }));
                                                                                                    }

                                                                                                    public ngOnDestroy(): void {
                                                                                                    this._subscription.unsubscribe();
                                                                                                    }
                                                                                                    }





                                                                                                    share|improve this answer













                                                                                                    The main idea behind this code is to keep all visited urls along with respective scrollY data in an array. Every time a user abandons a page (NavigationStart) this array is updated. Every time a user enters a new page (NavigationEnd), we decide to restore Y position or don't depending on how do we get to this page. If a refernce on some page was used we scroll to 0. If browser back/forward features were used we scroll to Y saved in our array. Sorry for my English :)



                                                                                                    import { Component, OnInit, OnDestroy } from '@angular/core';
                                                                                                    import { Location, PopStateEvent } from '@angular/common';
                                                                                                    import { Router, Route, RouterLink, NavigationStart, NavigationEnd,
                                                                                                    RouterEvent } from '@angular/router';
                                                                                                    import { Subscription } from 'rxjs/Subscription';

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

                                                                                                    private _subscription: Subscription;
                                                                                                    private _scrollHistory: { url: string, y: number } = ;
                                                                                                    private _useHistory = false;

                                                                                                    constructor(
                                                                                                    private _router: Router,
                                                                                                    private _location: Location) {
                                                                                                    }

                                                                                                    public ngOnInit() {

                                                                                                    this._subscription = this._router.events.subscribe((event: any) =>
                                                                                                    {
                                                                                                    if (event instanceof NavigationStart) {
                                                                                                    const currentUrl = (this._location.path() !== '')
                                                                                                    this._location.path() : '/';
                                                                                                    const item = this._scrollHistory.find(x => x.url === currentUrl);
                                                                                                    if (item) {
                                                                                                    item.y = window.scrollY;
                                                                                                    } else {
                                                                                                    this._scrollHistory.push({ url: currentUrl, y: window.scrollY });
                                                                                                    }
                                                                                                    return;
                                                                                                    }
                                                                                                    if (event instanceof NavigationEnd) {
                                                                                                    if (this._useHistory) {
                                                                                                    this._useHistory = false;
                                                                                                    window.scrollTo(0, this._scrollHistory.find(x => x.url ===
                                                                                                    event.url).y);
                                                                                                    } else {
                                                                                                    window.scrollTo(0, 0);
                                                                                                    }
                                                                                                    }
                                                                                                    });

                                                                                                    this._subscription.add(this._location.subscribe((event: PopStateEvent)
                                                                                                    => { this._useHistory = true;
                                                                                                    }));
                                                                                                    }

                                                                                                    public ngOnDestroy(): void {
                                                                                                    this._subscription.unsubscribe();
                                                                                                    }
                                                                                                    }






                                                                                                    share|improve this answer












                                                                                                    share|improve this answer



                                                                                                    share|improve this answer










                                                                                                    answered May 17 '18 at 9:58









                                                                                                    Vladimir TuryginVladimir Turygin

                                                                                                    184




                                                                                                    184























                                                                                                        0














                                                                                                        window.scrollTo() doesn't work for me in Angular 5, so I have used document.body.scrollTop like,



                                                                                                        this.router.events.subscribe((evt) => {
                                                                                                        if (evt instanceof NavigationEnd) {
                                                                                                        document.body.scrollTop = 0;
                                                                                                        }
                                                                                                        });





                                                                                                        share|improve this answer




























                                                                                                          0














                                                                                                          window.scrollTo() doesn't work for me in Angular 5, so I have used document.body.scrollTop like,



                                                                                                          this.router.events.subscribe((evt) => {
                                                                                                          if (evt instanceof NavigationEnd) {
                                                                                                          document.body.scrollTop = 0;
                                                                                                          }
                                                                                                          });





                                                                                                          share|improve this answer


























                                                                                                            0












                                                                                                            0








                                                                                                            0







                                                                                                            window.scrollTo() doesn't work for me in Angular 5, so I have used document.body.scrollTop like,



                                                                                                            this.router.events.subscribe((evt) => {
                                                                                                            if (evt instanceof NavigationEnd) {
                                                                                                            document.body.scrollTop = 0;
                                                                                                            }
                                                                                                            });





                                                                                                            share|improve this answer













                                                                                                            window.scrollTo() doesn't work for me in Angular 5, so I have used document.body.scrollTop like,



                                                                                                            this.router.events.subscribe((evt) => {
                                                                                                            if (evt instanceof NavigationEnd) {
                                                                                                            document.body.scrollTop = 0;
                                                                                                            }
                                                                                                            });






                                                                                                            share|improve this answer












                                                                                                            share|improve this answer



                                                                                                            share|improve this answer










                                                                                                            answered Feb 18 at 7:36









                                                                                                            Rohan KumarRohan Kumar

                                                                                                            35.4k96193




                                                                                                            35.4k96193

















                                                                                                                protected by eyllanesc Apr 15 '18 at 7:07



                                                                                                                Thank you for your interest in this question.
                                                                                                                Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).



                                                                                                                Would you like to answer one of these unanswered questions instead?



                                                                                                                這個網誌中的熱門文章

                                                                                                                Hercules Kyvelos

                                                                                                                Tangent Lines Diagram Along Smooth Curve

                                                                                                                Yusuf al-Mu'taman ibn Hud