Ben
Ben

Reputation: 41

On iOS devices, why does Ionic 4 Infinite Scroll jump to the top of the page when the ionInfinite event is fired?

Bug Report

Ionic version: [x] 4.x

Current behavior: On iOS devices, the screen jumps to the top of the list when items are added to a list via the infinite scroll component.

This is not a problem on the web (Chrome or Safari) or on Android devices.

iosInfiniteScrollIssue

Expected behavior: The screen scroll should not be affected by adding items to a list. The user should see new posts appear and continue scrolling as normal.

Steps to reproduce:

  1. Build the app in Xcode
  2. Run on a device
  3. Start scrolling down. Once you hit Post 5, you'll be sent to the top of the screen (Post 1).

Related code:

The repo is at https://github.com/bennyt2/ionic-infinite-scroll-test. Here are the two relevant files:

src/app/home/home.page.html: HTML that uses ion-infinite-scroll
<ion-content>
  <ng-container *ngFor="let post of posts;let i = index">
    <div class="post post-{{post % 2}}">Post {{post}}</div>
  </ng-container>

  <div class="no-posts-yet" *ngIf="posts.length === 0">No posts yet...</div>
  <div class="end-of-feed" *ngIf="allPostsLoaded">End of feed</div>

  <ion-infinite-scroll class="infinite-scroll" threshold="300px" (ionInfinite)="getMorePosts($event)">
    <ion-infinite-scroll-content loadingSpinner="circles" loadingText="Loading more posts...">
    </ion-infinite-scroll-content>
  </ion-infinite-scroll>

</ion-content>
src/app/home/home.page.ts: Component that handles post retrieval and the ionInfinite event
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-infinite-scroll-test',
  templateUrl: './infinite-scroll-test.page.html',
  styleUrls: ['./infinite-scroll-test.page.scss'],
})
export class InfiniteScrollTestPage implements OnInit {

  posts: number[] = [];
  maxPosts: number = 100;
  step: number = 5;
  loadedPosts: number = 0;
  allPostsLoaded: boolean = false;

  constructor() {
  }

  ngOnInit() {
    this.addPosts(5);
  }

  addPosts(number: number) {
    for (let i = 0; i < number; i++) {
      this.posts.push(this.posts.length + 1);
      this.loadedPosts = this.posts.length + 1;
    }
  }

  getMorePosts(event) {
    setTimeout(() => {
      this.addPosts(5);
      event.target.complete();

      // App logic to determine if all data is loaded
      // and disable the infinite scroll
      if (this.loadedPosts > this.maxPosts) {
        event.target.disabled = true;
        this.allPostsLoaded = true;
      }
    }, 500)
  }
}

Ionic info: from a terminal/cmd prompt and paste output below): -->

Ionic:

   Ionic CLI                     : 5.4.1 (/home/spikefalcontwo/.nvm/versions/node/v10.15.3/lib/node_modules/ionic)
   Ionic Framework               : @ionic/angular 4.11.7
   @angular-devkit/build-angular : 0.801.3
   @angular-devkit/schematics    : 8.1.3
   @angular/cli                  : 8.1.3
   @ionic/angular-toolkit        : 2.1.1

Capacitor:

   Capacitor CLI   : 1.4.0
   @capacitor/core : 1.4.0

Utility:

   cordova-res : not installed
   native-run  : not installed

System:

   NodeJS : v10.15.3 (/home/spikefalcontwo/.nvm/versions/node/v10.15.3/bin/node)
   npm    : 6.11.3
   OS     : Linux 5.0

Any idea what might be causing this?

Upvotes: 1

Views: 2078

Answers (3)

glennv
glennv

Reputation: 713

I had a similar issue but resolved it by adding a trackBy to my *ngFor. This allows angular to do more granular DOM updates i.e. only adding new items instead of re-rendering your list and causing the scroll position to be reset.

See the official angular docs for more info on how to use trackBy.

Upvotes: 2

Andrew Samole
Andrew Samole

Reputation: 742

I also had the same issue. I had an *ngIf for a loader when fetching more results, so every time I loaded more I was resetting the template. Check your *ngIfs!

Upvotes: 1

vaibhavkhot
vaibhavkhot

Reputation: 502

I had the same issue, ion-infinite-scroll element are direct children of the ion-content. The issue disappeared after wrapping it in a div. You could give it a try.

Upvotes: 4

Related Questions