Ionic 2: VirtualScroll items overlapping on first render


#1

My VirtualScroll cards are overlapping when first rendering:

Here’s a plunkr: http://plnkr.co/edit/etNNT8tKJB4yKMVV0F7a?p=preview

If I scroll the window a bit, it seems to sort itself out. Obviously this is not right.

How do I fix it so they render ok?

My markup (with div wrapper for custom component - as mentioned in the Ionic 2 docs):

  <ion-list #virtualScrollList [virtualScroll]="finalOrderedJobsList | jobFilter:query" [headerFn]="getHeaderDate" approxItemHeight="250px">
      <ion-item-divider *virtualHeader="let header" class="jobsListDivider">
        {{ header }}
      </ion-item-divider>  

      <div *virtualItem="let job">
        <jobCardVirtualScrollItem [job]="job"></jobCardVirtualScrollItem>
      </div>
  </ion-list>

Note: The cards will be variable in height. It’s not possible for me to make them all the same height fixed.


#2

There’s a warning in the docs about keeping dimensions fixed. I understand that you can’t have them all be the same height, but can you at least guarantee that a given jobCardVirtualScrollItem doesn’t ever change size?


#3

Hey thanks for your reply. Yes I can guarantee that. How does that help though?


#4

Well, if you weren’t sure about that (such as if something is coming in from a future and isn’t necessarily ready when the component is instantiated), then I thought that might be related to your layout problems, as maybe the virtual scroll thinks that the cards are smaller than they end up being.


#5

Right ok. If only there was some way to call the resize() method manually in the virtual scroll component class. I don’t think there’s any way to do it.


#6

Can you share a plunker what you did, it seems something went wrong in your layout design


#7

Here it is. I’ll also update the question text.

NOTE: I’ve added a setTimeout before applying the data to the list to simulate the data being loaded.

http://plnkr.co/edit/etNNT8tKJB4yKMVV0F7a?p=preview


#8

yes it’s your layout problem


#9

@Thavarajan Ok… so any indication of how to fix it along with that assertion? I don’t see anything different in your plunkr, the result is the same as mine.

Note: My example has the card wrapped in a div because in the real project, the card is in a separate component.
Ionic 2 docs specify to wrap custom components in a div in virtual scroll:

Custom Components
If a custom component is going to be used within Virtual Scroll, it’s best to wrap it with a good old

to ensure the component is rendered correctly. Since each custom component’s implementation and internals can be quite different, wrapping within a
is a safe way to make sure dimensions are measured correctly.
http://ionicframework.com/docs/api/components/virtual-scroll/VirtualScroll/
Thanks.

#10

use the ion-card outside of your template


#11

Thanks, but that’s just not correct. I have made a new plunkr, with larger cards, inline as you stated and they still overlap. This is clearly a framework issue and nothing to do with my markup, see below:

http://plnkr.co/edit/z0e2WINz7BQMo5MlWTTd?p=preview


#12

For anyone else having this issue, I have a workaround for now.

  1. Import ViewChild into your class:

import { ViewChild } from '@angular/core';

  1. Decorate your VirtualScroll list with an Id and reference it e.g.:

<ion-list #virtualScroll

export class MyJobsPage {
    @ViewChild('virtualScroll', { read: VirtualScroll }) virtualScroll: VirtualScroll;
    ...
  1. After binding your list data, do a resize manually e.g.:

             this.showLoadingSpinner();
             this.listData = whateverData;
             setTimeout(() => {
               this.virtualScroll.resize();
               this.hideLoadingSpinner();
             }, 1000);
    

Note: I added a loading spinner to cover the page so it looks a bit nicer before it resizes.