Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to scroll element into view when it's clicked

Am looking for something similar to scrollIntoView() within Ionic2 to use when I click on a button, for example.

None of the methods detailed in ion-content help.

like image 884
user1275105 Avatar asked Sep 08 '16 17:09

user1275105


6 Answers

Please take a look at this working plunker

You can use the scrollTo(x,y,duration) method (docs). The code is pretty simple, first we obtain the position of the target element (a <p></p> in this case) and then we use that in the scrollTo(...) method. First the view:

<ion-header>
  <ion-navbar primary>
    <ion-title>
      <span>My App</span>
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content>

  <button ion-button text-only (click)="scrollElement()">Click me</button>

  <div style="height: 600px;"></div>

  <!-- Notice the #target in the p element -->
  <p #target>Secret message!</p>

  <div style="height: 600px;"></div>

</ion-content>

And the component code:

import { ViewChild, Component } from '@angular/core';
import { NavController, Content } from 'ionic-angular';

@Component({
  templateUrl:"home.html"
})
export class HomePage {
  @ViewChild(Content) content: Content;
  @ViewChild('target') target: any;

  constructor() {   }

  public scrollElement() {
    // Avoid reading the DOM directly, by using ViewChild and the target reference
    this.content.scrollTo(0, this.target.nativeElement.offsetTop, 500);
  }
}
like image 181
sebaferreras Avatar answered Nov 12 '22 06:11

sebaferreras


The ion-content should have methods for scrolling to particular child elements, however deep. The current methods are okay, but one perspective of the purpose of ionic is to make laborious, boring code like document.getElementById obsolete.

The methods also lack control over the scroll animation.

Hence currently the best option is the scrollIntoView method. Attach an id to the element you wish to scroll to, then use getElementbyID to call scrollIntoView. So:

.html

...
<ion-row id="myElement">

...

</ion-row>

ts

...
 scrollToMyElement() {
    document.getElementById('myElement').scrollIntoView({
      behavior: 'smooth',
      block: 'center'
    });
  }

Then call the method on some DOM event or button click. If your element is conditional this will likely not work. Instead use a conditional hidden attribute or, if you must use ngIf, time the logic as such that the element is inserted first.

I've tried this with various other ionic (4) UI components and it works fine.

like image 26
Jai Avatar answered Nov 12 '22 05:11

Jai


For Ionic-4 there are multiple changes in the terms used

  1. Content is changed to IonContent
  2. scrollTo is changed to scrollToPoint
  3. ionic-angular is changed to @ionic/angular
  4. viewChild has to have { static: false } // only if you are using angular >8.0

Here is the code modified of the accepted answer for ionic-4

<ion-header>
      <ion-navbar primary>
        <ion-title>
          <span>My App</span>
        </ion-title>
      </ion-navbar>
</ion-header>
<ion-content>    
      <button ion-button text-only (click)="scrollElement(target)">Click me</button>

      <div style="height: 600px;"></div>

      <!-- Notice the #target in the p element -->
      <p #target>Secret message!</p>

      <div style="height: 600px;"></div>
</ion-content>

component Code :

import { ViewChild, Component } from '@angular/core';
import { IonContent } from '@ionic/angular'; // change-1

@Component({
  templateUrl:"home.html"
})
export class HomePage {
   @ViewChild('target', { static: false }) target: ElementRef;
   @ViewChild('ion_content', { static: false }) ionContent: IonContent; //change-2 for angular > 8.0 remove this for angular 6.x

  constructor() {   }

  public scrollElement($target) {
    this.ionContent.scrollToPoint(0, $target.offsetTop, 500); 
    //$target (prefered if you have multiple scroll target) could be this.target.nativeElement
  }
}
like image 2
himanshu goyal Avatar answered Nov 12 '22 05:11

himanshu goyal


I'd use an anker link in HTML.

Just give the elemnt and id="scrollXYZ" and wrap the button in an

Example:

<a href="#scrollXYZ"><button>Example</button></a>
<div id="scrollXYZ"><h2>Scroll to this</h2></div>
like image 1
jinnoflife Avatar answered Nov 12 '22 06:11

jinnoflife


I noticed the above solution don't work well with Angular Universal server-side rendering (SSR) due to document not being available server-side.

Hence I wrote a convenient plugin to achieve scrolling to elements in Angular 4+ that work with AoT and SSR

NPM
ngx-scroll-to

GitHub
ngx-scroll-to

like image 1
Nicky Avatar answered Nov 12 '22 06:11

Nicky


I was trying to do this in Ionic 3 and due to the fact that <Element>.offsetTop was returning10 (the padding on the top of the element) instead of the distance to the top of the page (much larger unknown number) I ending up just using <Element>.scrollIntoView(), which worked well for me.

To get the <Element> object I used document.getElementById(), but there are many other options on how to get a handle on that.

like image 1
azyth Avatar answered Nov 12 '22 05:11

azyth