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
Hide Menu Sidebar When Clicking Outside the Bar or the Button
Show Virtual Keyboard on Mobile Phones in JavaScript
How to Prevent Ajax Requests to Follow Redirects Using Jquery
How to Hide Div When You Scroll to Bottom and Show It Again When Scroll Up to Top
How to Set a Header Field on Post a Form
Input Field Value Should Not Be Greater Than Other Field Value
Html Input File Selection Event Not Firing Upon Selecting the Same File
Angular Conditional Readonly/Disable on Input Fields
How Display Selected Item from Bootstrap 4 Drop-Down Item Menu
How to Add or Update a Query String Parameter
How to Vertically and Horizontally Center a Component in React
Amount of All Goals of One Team (From Json)
How to Delete a Query String Parameter in JavaScript
Pass Input Tag Value to as Href Parameter
Generate Pdf from HTML in Div Using JavaScript
How to Enable Scrolling on Website That Disabled Scrolling
Javascript Regex - No White Space At Beginning + Allow Space in the Middle