16

I try to scroll to a fixed position, for example scrollTo(500, 20). Let's say that you are on a device, which has got a width of 300 pixel. The scroll target is now out of the screen scope, you have to scroll to the right.

I solved this by doing the following:

<ion-content>
    <ion-scroll scrollX="true" style="width:100%; height:100%; white-space: nowrap; ">
        <div style="width:1000px; ">
            [box1] [box2] [box3] [...]
        </div>
    </ion-scroll>
</ion-content>

Up to here everything is fine. The problem starts if i want to jump 500 pixel to the right by pressing a button for example. Swiping to the right works. I know that there is a function to do this for <ion-content>:

@ViewChild(Content) content: Content;
[...]
this.content.scrollTo(500, 500, 500); 

This unfortunately doesn't work in my case. I think the problem is that the content is related to the device size so the scrollTo() method does not take affect for <ion-scoll>. How can I use the scrollTo() method for <ion-scroll> instead of <ion-content>?

Thanks for any help!

sebaferreras
  • 44,206
  • 11
  • 116
  • 134
Tobias Bambullis
  • 736
  • 5
  • 17
  • 45
  • 1
    not sure if this is the cause.. but `ion-scroll` generally needs specific dimensions .. `%` doesnt work generally – Suraj Rao May 24 '17 at 07:30
  • in my case it is working well. I can scroll to the right and there is a scroll bar which is showing the scrollable area is probably 1000px wide. My problem is that ion-content fits to the screen dimensions and ion-scroll doesn't react to content.scrollTo(), because content has a width of 300 pixel and ion-scroll a width of 1000px. – Tobias Bambullis May 26 '17 at 13:30

5 Answers5

10

How can I use the scrollTo() method for <ion-scroll> instead of <ion-content>?

I'm still working on how to animate the scroll, but at least this may be considered as a solution for your scenario. Please take a look at this plunker.

Since we can't use theion-content for scrolling, I though about getting the instance of the Scroll, then accessing the inner html scroll element, and then using the element.scrollLeft property to scroll on that element:

The element.scrollLeft property gets or sets the number of pixels that an element's content is scrolled to the left.

So in the component code:

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

@Component({...})
export class HomePage {
  @ViewChild('scroll') scroll: any;

    constructor() {}

    public backToStart(): void {
      this.scroll.scrollElement.scrollLeft = 0;
    }

    public scrollToRight(): void {
      this.scroll.scrollElement.scrollLeft = 500;
    }

}

And in the view:

<ion-content padding>
  <ion-scroll #scroll scrollX="true" style="width:100%; height:150px; white-space: nowrap;">
        <div  style="width:1000px;">
            <div style="display:inline-block;height:100px;width:100px;border:1px solid black;"></div>
            <div style="display:inline-block;height:100px;width:100px;border:1px solid red;"></div>
            <div style="display:inline-block;height:100px;width:100px;border:1px solid blue;"></div>
            <div style="display:inline-block;height:100px;width:100px;border:1px solid green;"></div>
            <div style="display:inline-block;height:100px;width:100px;border:1px solid grey;"></div>
            <div style="display:inline-block;height:100px;width:100px;border:1px solid brown;"></div>
            <div style="display:inline-block;height:100px;width:100px;border:1px solid yellow;"></div>
            <div style="display:inline-block;height:100px;width:100px;border:1px solid orange;"></div>
            <div style="display:inline-block;height:100px;width:100px;border:1px solid pink;"></div>
            <div style="display:inline-block;height:100px;width:100px;border:1px solid violet;"></div>
        </div>
    </ion-scroll>

    <button (click)="backToStart()" ion-button text-only>Go to start</button>
    <button (click)="scrollToRight()" ion-button text-only>Scroll to right!</button>
</ion-content>

By doing this.scroll.scrollElement.scrollLeft = 500;, we can scroll the content of the ion-scroll 500px to the right. We can then go back to the start again by doing this.scroll.scrollElement.scrollLeft = 0;.

sebaferreras
  • 44,206
  • 11
  • 116
  • 134
  • 1
    very nice answer, thank you! Unfortunately I get an error message: "Cannot set property 'scrollLeft' of undefined". If i write console.log(this.scroll) i get this: _scrollContent: ElementRef, nativeElement: div.scroll-content. Do you have a solution for this? – Tobias Bambullis May 27 '17 at 16:59
  • 1
    Hmm, maybe we're using different versions of Ionic. Instead of `this.scroll.scrollElement.scrollLeft = 500;` try with `this.scroll. nativeElement.scrollLeft = 500;` – sebaferreras May 27 '17 at 17:05
  • 3
    i found it out, it is this.scroll._scrollContent.nativeElement.scrollLeft! Thank you very much!! – Tobias Bambullis May 27 '17 at 17:07
  • Glad to hear that! :) – sebaferreras May 27 '17 at 17:08
  • Scroll is not smooth in this case. Is there content.scrollTo(x, y, delay) kinda thing for ion-scroll? – Vivek Sinha Aug 29 '17 at 12:07
  • 3
    Great answer! I created an animation for smooth scrolling without use of any js library https://gist.github.com/sgotre/e070ef5cce1c778a6380d4c139047e13 – sgotre Oct 27 '17 at 17:27
  • i am using my ion-scroll inside ngFor and the above code `this.scroll.scrollElement.scrollLeft = 500;` is working for the first object only is there any solution – Mohan Gopi Dec 08 '17 at 12:58
  • hi, can i give that number '500' pixels into some of the percentage – Hari9513 Dec 11 '18 at 05:53
6

By content scrolling

@ViewChild(Content) content: Content;
  this.content.scrollTo 

By id #scroll

@ViewChild('scroll') scroll: any;  
this.scroll.scrollElement.scrollLeft = 500;

This above method is working fine for top bottom scrolling but in the case of horizontal/scrollX not working so by below code i resolve my solution may hope it will helpful for you.

TypeScript

scrollmain(elementId, index) {
   console.info('elementId', elementId)
   var el = document.getElementById(elementId);
   el.scrollIntoView({ behavior: "smooth" });
}

HTML

<ion-scroll #scroll scrollX="true" style="width:100%;white-space: 
          nowrap; height: 60px">
    <ion-segment *ngIf="mcqdata" color="appmaincolor">
        <ion-segment-button *ngFor="let mcq of mcqdata; let i=index;" [id]="mcq.ques_id" value="{{mcq.ques_id}}" (ionSelect)="scrollmain(mcq.ques_id,i)"
            [ngClass]="{'active': selectedIdx == i}">
            <strong>Queastion{{i+1}}</strong>
        </ion-segment-button>
    </ion-segment>
</ion-scroll>
Sathyajith
  • 3,836
  • 3
  • 15
  • 28
Manoj Bhardwaj
  • 736
  • 1
  • 9
  • 25
3

To add to the answers above, this will handle smooth scrolling.

Name the scroll element in your .html

<ion-scroll #scroll>

Import the scroll.

import { Scroll } from 'ionic-angular';

Reference the scroller in the .ts

@ViewChild('scroll') scroll: any;

Add this code where its needed:

this.scroll._scrollContent.nativeElement.scrollTo({ left: 0, top: 0, behavior: 'smooth' });

Hope that helps somebody.

Blueberry
  • 2,211
  • 3
  • 19
  • 33
0

Why don't you get the dimensions of the element that you want to scroll to first? Assign an id to your ion-scroll in html file, then you can use this function:

scrollToElement(id) { 
    var el = document.getElementById(id);
    var rect = el.getBoundingClientRect();
    // scrollLeft as 0px, scrollTop as "topBound"px, move in 800 milliseconds
    this.content.scrollTo(0, rect.top, 800);
}

From this documentation: The returned value of getBoundingClientRect left, top, right, bottom, x, y, width, height properties describing the border-box in pixels. Properties other than width and height are relative to the top-left of the viewport.

Looking at your code, I don't think you need ion-scroll, you should be able to just assign an id to your div and get the result you want.

Ari
  • 7,251
  • 11
  • 40
  • 70
  • hi. Thanks for you answer. My problem isn't based on finding the right position of the element i would like to scroll to. I can write this.content.scrollTo(500, 0, 800); directly but nothing happens. My problem is that ion-content fits to the screen dimensions and ion-scroll doesn't react to content.scrollTo(), because content has a width of 300 pixel and ion-scroll a width of 1000px. If I remove ion-scroll, i cannot scroll to the right. I tried a lot to make content scrolling. But everything didn't work unfortunately :( – Tobias Bambullis May 26 '17 at 13:36
  • Do you know why it doesn't work when you remove ion scroll? Can you scroll manually in that case? – Ari May 26 '17 at 15:01
  • no i couldn't. Every solution I found uses ion-scroll. The main problem of ion-content was that i couldn't scroll to the right. I think ion-content is not made for this. – Tobias Bambullis May 26 '17 at 17:14
0

You can replace this.content.scrollTo(...) with this.content._scrollContent.nativeElement.scrollTo(...)

double-beep
  • 5,031
  • 17
  • 33
  • 41