16

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.

sebaferreras
  • 44,206
  • 11
  • 116
  • 134
user1275105
  • 2,643
  • 5
  • 31
  • 45

8 Answers8

14

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);
  }
}
sebaferreras
  • 44,206
  • 11
  • 116
  • 134
3

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.

Jai
  • 2,768
  • 24
  • 20
  • This works very well.. but not angular specific code, :) use @ViewChild('myDiv') myDiv: ElementRef; this.myDiv.nativeElement.scrollIntoView({ behavior: 'smooth', block: 'center' }); – Divek John Mar 26 '21 at 14:21
3

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
  }
}
himanshu goyal
  • 363
  • 2
  • 9
1

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>
jinnoflife
  • 126
  • 1
  • 9
1

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

Nicky
  • 3,607
  • 6
  • 33
  • 64
1

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.

azyth
  • 698
  • 5
  • 19
0

In Ionic 4 the scroll function is renamed to scrollToPoint().

Screenshot from Ionic docs

Sinandro
  • 2,426
  • 3
  • 21
  • 36
0

Can I use scrollToPoint on div instead of content when I have fixed content and the scroll on div or form.

Tareq
  • 33
  • 3
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Nov 05 '21 at 10:29
  • If you have a new question, please ask it by clicking the [Ask Question](https://stackoverflow.com/questions/ask) button. Include a link to this question if it helps provide context. - [From Review](/review/late-answers/30265013) – D.Zotov Nov 05 '21 at 12:01