'Scroll to element on click in Angular 4

I want to be able to scroll to a target when a button is pressed. I was thinking something like this.

<button (click)="scroll(#target)">Button</button>

And in my component.ts a method like.

scroll(element) {
    window.scrollTo(element.yPosition)
}

I know that the code above is not valid but just to show what I was thinking. I've just started to learn Angular 4 with no previous experience of Angular. I've been searching around for something like this but all the examples are in AngularJs which differs alot to Angular 4



Solution 1:[1]

You could do it like this:

<button (click)="scroll(target)"></button>
<div #target>Your target</div>

and then in your component:

scroll(el: HTMLElement) {
    el.scrollIntoView();
}

Edit: I see comments stating that this no longer works due to the element being undefined. I created a StackBlitz example in Angular 7 and it still works. Can someone please provide an example where it does not work?

Solution 2:[2]

In Angular 13 works perfect

HTML

<button (click)="scroll(target)">Click to scroll</button>
<div #target>Your target</div>

In component

scroll(el: HTMLElement) {
    el.scrollIntoView({behavior: 'smooth'});
}

Solution 3:[3]

Here is how I did it using Angular 4.

Template

<div class="col-xs-12 col-md-3">
  <h2>Categories</h2>
  <div class="cat-list-body">
    <div class="cat-item" *ngFor="let cat of web.menu | async">
      <label (click)="scroll('cat-'+cat.category_id)">{{cat.category_name}}</label>
    </div>
  </div>
</div>

add this function to the Component.

scroll(id) {
  console.log(`scrolling to ${id}`);
  let el = document.getElementById(id);
  el.scrollIntoView();
}

Solution 4:[4]

There is actually a pure javascript way to accomplish this without using setTimeout or requestAnimationFrame or jQuery.

In short, find the element in the scrollView that you want to scroll to, and use scrollIntoView.

el.scrollIntoView({behavior:"smooth"});

Here is a plunkr.

Solution 5:[5]

Jon has the right answer and this works in my angular 5 and 6 projects.

If I wanted to click to smoothly scroll from navbar to footer:

<button (click)="scrollTo('.footer')">ScrolltoFooter</button>
<footer class="footer">some code</footer>

scrollTo(className: string):void {
   const elementList = document.querySelectorAll('.' + className);
   const element = elementList[0] as HTMLElement;
   element.scrollIntoView({ behavior: 'smooth' });
}

Because I wanted to scroll back to the header from the footer, I created a service that this function is located in and injected it into the navbar and footer components and passed in 'header' or 'footer' where needed. just remember to actually give the component declarations the class names used:

<app-footer class="footer"></app-footer>

Solution 6:[6]

Another way to do it in Angular:

Markup:

<textarea #inputMessage></textarea>

Add ViewChild() property:

@ViewChild('inputMessage')
inputMessageRef: ElementRef;

Scroll anywhere you want inside of the component using scrollIntoView() function:

this.inputMessageRef.nativeElement.scrollIntoView();

Solution 7:[7]

You can scroll to any element ref on your view by using the code block below. Note that the target (elementref id) could be on any valid html tag.

On the view(html file)

<div id="target"> </div>
<button (click)="scroll()">Button</button>
 

  

on the .ts file,

scroll() {
   document.querySelector('#target').scrollIntoView({ behavior: 'smooth', block: 'center' });
}

Solution 8:[8]

In Angular you can use ViewChild and ElementRef: give your HTML element a ref

<div #myDiv > 

and inside your component:

import { ViewChild, ElementRef } from '@angular/core';
@ViewChild('myDiv') myDivRef: ElementRef;

you can use this.myDivRef.nativeElement to get to your element

Solution 9:[9]

You can achieve that by using the reference to an angular DOM element as follows:

Here is the example in stackblitz

the component template:

<div class="other-content">
      Other content
      <button (click)="element.scrollIntoView({ behavior: 'smooth', block: 'center' })">
        Click to scroll
      </button>
    </div>
    <div id="content" #element>
      Some text to scroll
</div>

Solution 10:[10]

If the scroll goes too far

Get correct y coordinate and use window.scrollTo({top: y, behavior: 'smooth'})

Set different y coordinate if using multiple elements

Html file

<div class="sub-menu">
  <button (click)="scroll('#target1', -565)">Target One</button>
  <button (click)="scroll('#target2', -490)">Target Two</button>
</div>

<div>
  <div id="target1">Target One</div>
</div>

<div>
  <div id="target2">Target Two</div>
</div>

ts file

  scroll(elem: string, offset: number) {
    const yOffset = offset;
    const element = document.querySelector(elem)!;
    const y = element.getBoundingClientRect().top + window.pageYOffset + yOffset;

    window.scrollTo({ top: y, behavior: 'smooth' })
  }

Solution 11:[11]

I need to do this trick, maybe because I use a custom HTML element. If I do not do this, target in onItemAmounterClick won't have the scrollIntoView method

.html

<div *ngFor"...">
      <my-component #target (click)="clicked(target)"></my-component>
</div>

.ts

onItemAmounterClick(target){
  target.__ngContext__[0].scrollIntoView({behavior: 'smooth'});
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3 BuZZ-dEE
Solution 4 Jon
Solution 5 Stephen E.
Solution 6 BuZZ-dEE
Solution 7 BuZZ-dEE
Solution 8 BuZZ-dEE
Solution 9
Solution 10 Harvey
Solution 11 SimoneMSR