Ionic 2: VirtualScroll items overlapping on first render

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.

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?

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

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.

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.

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

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

yes it’s your layout problem

@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.

use the ion-card outside of your template

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

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.