Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ionic 2 - virtual scrolling not working as expected

Tags:

ionic2

I don't know why the virtual scrolling I implemented is looking weird.

I have a list of words and I wanna show them in a page. earlier I iterated these words using a for loop but the scrolling performance was horrible in android devices. So I decided to implement basic virtual scrolling as mentioned in ionic's official documentation.

http://rhymebrain.com/talk?function=getRhymes&word=baby

This is the data That I'm trying to iterate. I only need the words, no other info.

Code for my virtual scroll looks like this:

<ion-card *ngIf="words?.length > 0">
  <ion-card-header>rhymes with...</ion-card-header>
  <ion-card-content>
    <ion-list [virtualScroll]="words" [approxItemHeight]=" '500px' ">
      <button *virtualItem="let word" ion-button round small>
        {{word.word}}
      </button>
    </ion-list>
  </ion-card-content>
</ion-card>

In my web browser, the results I got are terrible. I will share some screens:

Pic 1: User searches for a word to fetch all rhymes but no data is shown even when response is not null.

enter image description here

Pic 2: If I navigate to another page and come back, I see a few of the rhymes.

enter image description here

Pic 3: If I repeat step 2 or scroll a little down, I see few more words. It looks so weird.

enter image description here enter image description here

I have no idea why virtual scroll is acting like this. Can anyone tell me what mistake I made or a better solution for this?

thanks in advance

like image 956
Lonewolf Avatar asked May 02 '17 12:05

Lonewolf


1 Answers

There's a few issues with virtual scroll that are unfortunately not documented. Fixing all these should get you in the right direction.

Predefined Height

All ancestors of your [virtualScroll] must have a predefined height. The virtual list will grab the elements height and based on that, populate the cells. If the height is 0, it will populate only a few cells which make up for the buffer space of scrolling quickly. Don't use inline CSS but for simplicity here's an example.

<ion-content>
  <div style="height:100%">
    <ion-list [virtualScroll]="items" approxItemHeight="50px">
      ...
    </ion-list>
  </div>
</ion-content>

Define Approximate Item Height

In the example above you can see I'm setting approxItemHeight. This is an important step that helps the virtual list with it's calculations.

Don't Wrap In If Statement

Unfortunately you can't put your virtual scroll inside an ngIf, ticket. Your virtual scroll needs to be rendered at the beginning of your components life cycle. So if you wrapped your virtual scroll inside of a condition which from the time of the constructor was equal to true, the issue would not exist. However if some point later on the condition becomes true, you'll have to redesign your implementation.

What I did for this was switch from using *ngIf to using [ngClass]="virtualClass". When I want to hide the virtual scroll I will set virtualClass = 'virtual-hide'.

.virtual-hide { 
  overflow: hidden;
  visibility: hidden;
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
}

You can't use display: none since this will not render the virtual scrolls height, same problem we want to resolve. The above CSS should allow for the element to be on screen and take up the correct amount of space while not appearing to actually be there. This code might need to be adjusted based on your implementation.

Ensure Items Exist

Switching to using ngClass from ngIf will mean your virtual scroll is always in the DOM. Because of this, you must make sure that items (the array for [virtualScroll]) is always set. So make sure it's never undefined or null, instead set it to [] if you want it to be empty.

like image 164
cnotethegr8 Avatar answered Nov 17 '22 01:11

cnotethegr8