Recently I was implementing in Angular a requirement that demanded the following:
"After pressing a button, if some specific data is returned, present a warning with a link saying that the specific data exists. After clicking on that link, scroll down to the grid containing the data".
First, I tried the simplest solution, which was the use of DOM commands like Element.scrollIntoView(), or
document.getElementById("<yourTarget>").scrollIntoView({
behavior: "smooth",
block: "start",
inline: "nearest"
});
(Remeber to add id="<yourtarget"
where you want to scroll)
It worked on development, and it was quite easy, but after deploying to production environment I noticed that the scroll was not working!
So, I tried another way, using Angular's ViewportScroller.
In order to do that, you have to inject ViewportScroller at Component's constructor, like constructor(private scroller: ViewportScroller)
and just call this.scroller.scrollToAnchor("<yourTarget>");
. Again, no big deal, and again it was NOT WORKING on production environment.
The third way to do it, is to use Router to provide navigation to the anchor I wanted. Similarly to the last option, inject Router to constructor, like constructor(private router: Router)
, and use the command:
this.router.navigate([], { fragment: "<yourTarget>" });
Finally it DID WORK on production environment! I don't know for sure why the previous methods failed, I read some sources that says Angular Material blocks scrolling, but I'm not sure.
In order to present the different options there's a Stackblitz as an example.
There you can click on tree buttons, each one using a different method to scroll down to some anchor.
Hope it helps someone :)
Top comments (12)
Gracias, buenas ideas!
You also could just do this in the template itself: StackBlitz
Helped me, thanks. I'm looking at building elearning which has sections hidden until you click the continue button, then it scrolls down to the next section. Needed a setTimeout for it to scroll to previously hidden divs but works very nicely. Thanks.
you're welcome!
Hello,
In my case the other way to scroll (document and scroller way) were sometimes not working because triggering at a moment in the loading process where the element was not on screen. It is in my case a table.
So probably we need to trigger them once we are sure the html element we want to scroll to in in the DOM.
Use router is not correct solution IMHO. Did you try to click to button "scroll to blue Div" and than scroll up a click the button again? Nothing will happen because URL has been already changed.
I am trying this now in Angular 12 version, you are gonna need to add the following code in app-routing, for the fragment route to work now. "onSameUrlNavigation: 'reload'" option will resolve the issue.
const routerOptions: ExtraOptions = {
scrollPositionRestoration: 'enabled',
anchorScrolling: 'enabled',
onSameUrlNavigation: 'reload',
};
imports: [RouterModule.forRoot(routes, routerOptions)],
You just saved me a ton of time.
Everyone has a top choice. There's no 100% right or wrong.
Thanks!
with non-static html it wouldn't work
I've done the third one for the blue box and there's no error, but it's just not working.