Scroll to Element from Typescript Code (Angular 5)

Scroll to element from typescript code (angular 5)

use the power of view child

@ViewChild('scroll', { read: ElementRef }) public scroll: ElementRef<any>;

ngAfterViewChecked() {
this.scrollBottom()
}

public scrollBottom() {
this.scroll.nativeElement.scrollTop = this.scroll.nativeElement.scrollHeight;
}

slackblitz link

html

    <div style="height:200px; overflow-y:auto;" #scroll>
<div *ngFor="let i of list">
{{i.name}}
<br>
</div>
</div>


<button (click)="Add()">Add</button>

<button (click)="scrollToTop()">Scroll to top</button>
<button (click)="scrollBottom()">Scroll to bottom</button>

component

import { Component, ElementRef, ViewChild } from '@angular/core';

@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})

export class AppComponent {
@ViewChild('scroll', { read: ElementRef }) public scroll: ElementRef<any>;



list = [{ name: 'Nam porta orci sed enim imperdiet, et vulputate erat luctus. Integer a tortor blandit, eleifend velit id, eleifend libero. Quisque quis congue ex, vitae suscipit ipsum. Aliquam felis enim, bibendum vel dolor et, dapibus fringilla felis. Sed magna ipsum, congue molestie nisl non, commodo pellentesque felis. Mauris hendrerit rhoncus turpis, at lacinia metus finibus eget. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Aliquam ligula risus, tincidunt ac diam vehicula, fringilla blandit sapien. Ut dictum a nunc id tempus. Nulla sed felis id quam hendrerit volutpat eget at velit. Praesent finibus, mauris ac molestie laoreet, erat est mattis velit, ac tincidunt nulla enim ac felis. In hac habitasse platea dictumst. Nam neque nibh, tempus a velit a, porttitor finibus quam. Nunc pharetra est eget urna mollis, sed facilisis eros pulvinar. Duis ac metus egestas, malesuada ligula eu, congue magna.Nam porta orci sed enim imperdiet, et vulputate erat luctus. Integer a tortor blandit, eleifend velit id, eleifend libero. Quisque quis congue ex, vitae suscipit ipsum. Aliquam felis enim, bibendum vel dolor et, dapibus fringilla felis. Sed magna ipsum, congue molestie nisl non, commodo pellentesque felis. Mauris hendrerit rhoncus turpis, at lacinia metus finibus eget. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Aliquam ligula risus, tincidunt ac diam vehicula, fringilla blandit sapien. Ut dictum a nunc id tempus. Nulla sed felis id quam hendrerit volutpat eget at velit. Praesent finibus, mauris ac molestie laoreet, erat est mattis velit, ac tincidunt nulla enim ac felis. In hac habitasse platea dictumst. Nam neque nibh, tempus a velit a, porttitor finibus quam. Nunc pharetra est eget urna mollis, sed facilisis eros pulvinar. Duis ac metus egestas, malesuada ligula eu, congue magna.Nam porta orci sed enim imperdiet, et vulputate erat luctus. Integer a tortor blandit, eleifend velit id, eleifend libero. Quisque quis congue ex, vitae suscipit ipsum. Aliquam felis enim, bibendum vel dolor et, dapibus fringilla felis. Sed magna ipsum, congue molestie nisl non, commodo pellentesque felis. Mauris hendrerit rhoncus turpis, at lacinia metus finibus eget. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Aliquam ligula risus, tincidunt ac diam vehicula, fringilla blandit sapien. Ut dictum a nunc id tempus. Nulla sed felis id quam hendrerit volutpat eget at velit. Praesent finibus, mauris ac molestie laoreet, erat est mattis velit, ac tincidunt nulla enim ac felis. In hac habitasse platea dictumst. Nam neque nibh, tempus a velit a, porttitor finibus quam. Nunc pharetra est eget urna mollis, sed facilisis eros pulvinar. Duis ac metus egestas, malesuada ligula eu, congue magna.' }];



public Add() {
this.list.push({ name: 'Nam porta orci sed enim imperdiet, et vulputate erat luctus. Integer a tortor blandit, eleifend velit id, eleifend libero. Quisque quis congue ex, vitae suscipit ipsum. Aliquam felis enim, bibendum vel dolor et, dapibus fringilla felis. Sed magna ipsum, congue molestie nisl non, commodo pellentesque felis. Mauris hendrerit rhoncus turpis, at lacinia metus finibus eget. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Aliquam ligula risus, tincidunt ac diam vehicula, fringilla blandit sapien. Ut dictum a nunc id tempus. Nulla sed felis id quam hendrerit volutpat eget at velit. Praesent finibus, mauris ac molestie laoreet, erat est mattis velit, ac tincidunt nulla enim ac felis. In hac habitasse platea dictumst. Nam neque nibh, tempus a velit a, porttitor finibus quam. Nunc pharetra est eget urna mollis, sed facilisis eros pulvinar. Duis ac metus egestas, malesuada ligula eu, congue magna.' });

console.log(this.scroll.nativeElement.scrollHeight);

}

ngAfterViewChecked() {
this.scrollBottom()
}

public scrollBottom() {
this.scroll.nativeElement.scrollTop = this.scroll.nativeElement.scrollHeight;
}

public scrollToTop() {
this.scroll.nativeElement.scrollTop = 0;
}
}

Update 1:

ngAfterViewChecked() {
// this.scrollToTop()
}

public scrollBottom() {
console.log(this.scroll.nativeElement.scrollTop);
this.scroll.nativeElement.scrollTop = this.scroll.nativeElement.scrollHeight;

}

comment out the ngAfterViewChecked()
you can able to scroll down

By default, I set it to scroll up after init

Try the same link to view the update source

Scroll to class in angular 5

this works, but damn it's ugly

 window.setTimeout(() => {
if ($('.cal-open').length > 0) {
$('html, body').animate({
scrollTop: $('.cal-open').offset().top - 80
}, 100);
}
}, (250));

Angular 5 Scroll to top on every Route click

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


Option1:

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

app.component.html

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

app.component.ts

onActivate(event) {
// window.scroll(0,0);

window.scroll({
top: 0,
left: 0,
behavior: 'smooth'
});

//or document.body.scrollTop = 0;
//or document.querySelector('body').scrollTo(0,0)
...
}

As the smooth scroll is not implemented well in Safari, use, for exemple, this solution for a smooth scroll:

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

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

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

Option2:

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

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

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


Option3:

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

query(':enter, :leave', style({ position: 'fixed' }), { optional: true }) 

How to smooth scroll to page anchor in angular 4 without plugins properly?

I was looking for a similar solution and tried to use the ngx-scroll-to package and found that its not working in latest version of angular (angular 6+) so decided to look into other option and found a solution which uses the browser's native scrollIntoView and this seems to be the best solution so far

HTML code :

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

Ts code :

scrollToElement($element): void {
console.log($element);
$element.scrollIntoView({behavior: "smooth", block: "start", inline: "nearest"});
}

Angular - Button Scroll to Top

Use hostListener to listen window scroll event,Then Use angular ViewPortScroller service, which provide scrollToPostion method use that to scroll to specified position.

Try this:

component.ts

@HostListener('window:scroll', ['$event']) onScroll(event){
this.pageYoffset = window.pageYOffset;
}

constructor(private scroll: ViewportScroller) { }

scrollToTop(){
this.scroll.scrollToPosition([0,0]);
}

Working Example

How can I activate the specific nav from header while scrolling to the corresponding section in Angular?

We can create our own directive. Suppose we have the following markup.

<div class="header">
<div class="nav-link" [ngClass]="{'active': currentSection === 'section1'}">section 1</div>
<div class="nav-link" [ngClass]="{'active': currentSection === 'section2'}">section 2</div>
<div class="nav-link" [ngClass]="{'active': currentSection === 'section3'}">section 3</div>
<div class="nav-link" [ngClass]="{'active': currentSection === 'section4'}">section 4</div>
<div class="nav-link" [ngClass]="{'active': currentSection === 'section5'}">section 5</div>
</div>
<div sectionScroll (sectionChange)="onSectionChange($event)">
<div id="section1" class="section">
Section 1
</div>
<div id="section2" class="section">
Section 2
</div>
<div id="section3" class="section">
Section 3
</div>
<div id="section4" class="section">
Section 4
</div>
<div id="section5" class="section">
Section 5
</div>
</div>

And the component itself:

import { Component } from '@angular/core';

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent {
currentSection = 'section1';

constructor() {}

onSectionChange(sectionId: string) {
this.currentSection = sectionId;
}
}

There's a directive in the parent block that we will be looking at below and sectionChange that calls the method onSectionChange only when the directive onSectionChange sends a value. There's a unique ID for each section which is needed in order to determine the current active section within the directive. The directive itself looks as follows.

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

@Directive({
selector: '[sectionScroll]',
})
export class SectionScrollDirective {
private spiedTags = ['DIV'];

@Output() public sectionChange = new EventEmitter<string>();
private currentSection!: string;

constructor(private _el: ElementRef) {}

@HostListener('document:mousewheel', ['$event'])
onScroll(event: any) {
let currentSection = '';
const childrens = this._el.nativeElement.children;
const top = event.target.scrollTop;
const parentOffset = event.target.offsetTop;
for (let i = 0; i < childrens.length; i++) {
const element = childrens[i];
if (this.spiedTags.some((spiedTag) => spiedTag === element.tagName)) {
if (element.offsetTop - parentOffset <= top) {
currentSection = element.id;
}
}
}
if (currentSection !== this.currentSection) {
this.currentSection = currentSection;
this.sectionChange.emit(this.currentSection);
}
}
}

The array spiedTags stores the tag names which we will be tracking.

Using HostListener (see https://angular.io/api/core/HostListener), we listen to the scroll event on the element to which the directive is attached to. Every time the scroll event is triggered, the onScroll method is called that goes through the elements of the array with child elements of the element to which the directive is attached and determines the element that crosses the top part of the browser window and after that assigns a unique identifier to currentSection that we determined in the template for each section. After that we check that if the section has changed, then we have to send a new section's value from the directive.

currentSection within the component is required in order to determine which reference in navbar will be used to assign the active class to using the directive ngClass.

Scroll to a certain element of the current page in Angular 4

You can do this with javascript:

gotoTop() {
let el = document.getElementById('navbar');
el.scrollTop = el.scrollHeight;
}

This will bring the DOM element with id="navbar" into view when the method is called. There's also the option of using Element.scrollIntoView. This can provide a smooth animation and looks nice, but isn't supported on older browsers.

If the element is in a different component you can reference it several different ways as seen in this question.

The easiest method for your case would likely be:

import { ElementRef } from '@angular/core'; // at the top of component.ts

constructor(myElement: ElementRef) { ... } // in your export class MyComponent block

and finally

gotoTop() {
let el = this.myElement.nativeElement.querySelector('nav');
el.scrollIntoView();
}

Working plunker.



Related Topics



Leave a reply



Submit