Angular 5 scroll to top when change route năm 2024
By default, when a new route is activated, Angular’s router doesn’t touch the scroll position. At least this is still true of Angular 9, even if it’ll probably change in the future. Show
This is problematic in some cases. For instance, if you are on a page that ends up being longer that the viewport, scroll down and navigate to a new route (e.g., using a Also, if you navigate back/forward using the browser’s buttons, the scroll position will not be restored either. A sad situation indeed… Fortunately, there are different solutions to fix that. Let’s see how. Bazooka approachWhen a new route is activated, an “activated” event is emitted, which you can react to. So you could do something like this: In the example App component above, notice that I’ve added a ` Content` anchor so that I can access the ## element from the controller (using the ViewChild decorator).Also, I’ve attached an event handler to the Let’s now look at what we can do with this in the controller: In the controller’s Content` ## element from the DOM and set the nativeElement’s scrollTop property to 0, effectively bringing the scrollbar back to the top of the page.This ensures that the actual content pane of the application is scrolled back on top whenever we arrive on a new route. It does work for my use case but is far from perfect. Most notably, if I navigate back to a previous page, it’ll also be scrolled back on top, which is not always what you might want. So, how can we improve this? First of all, if you have pages that take a while to load, you could make use of the Window.scrollTo API to scroll to where you want (e.g., an anchor or something), or using the ViewportScroller of Angular, but this would be a nightmare to tain as it would have to be handled page per page. Moreover, it would only work if your page layout relies on the ## viewport (i.e., if the whole layout scrolls).Ideally, if you need to remember and restore scroll positions when navigating back/forward, it’s probably better to have a more powerful solution. Angular’s built-in (but broken?) solutionSince version 6, Angular has built-in support for restoring the scroll position when navigating using the Angular router. Note that, as of Angular 9, that feature still isn’t enabled by default. To enable (as it is called), you need to adapt your app-routing.module.ts file (i.e., the place where you should find the In the example above, I’ve enabled the That setting accepts multiple values:
When it is set to ` Content`0, it:
Unfortunately, even if it sounds perfect, as explained in this issue, it doesn’t solve all the problems and doesn’t work in all situations. For instance, in my case, it didn’t help one bit because it only takes care of the scroll position of the ## viewport. Since my application’s layout has a fixed top/left bar, only the content pane (contained in my “##” element) can scroll. This means that scrolling to the top of the page can’t be done simply by using Window.scrollTo(…). In practice, the scroll position restoration feature of Angular doesn’t do anything useful for my application. Another case where it won’t be able to help is when your content takes time to load. If that’s the case then, depending on the timing, the Angular support for scroll position restoration might fail and put the page on top even if should have restored the scroll position lower.. The thing is that it isn’t aware of your content at all. Also, it isn’t able to tell the difference between route changes that replace the entire viewport of only change a subset of the page (e.g., changing the contents of a secondary router outlet). In Angular’s defense, restoring the scroll position isn’t that easy and certainly hard to handle for all cases alike. Other libraries like React and Vue also face the same kinds of issues. Check out the github issue for other improvement ideas. Bummer. Let’s try something else. Custom router scroll serviceAs far as I’m concerned the bazooka and built-in solution of Angular didn’t cut it. I’ve thus started looking for alternatives. After searching for a bit, I’ve stumbled upon a great (as usual) article from Angular In Depth which proposed to leverage RxJS and router events to keep track of scroll positions and restore those if/when needed. Based on that article, its comments and some personal wizardry, I’ve written an Angular service that:
|