Ionic Info
Run ionic info
from a terminal/cmd prompt and paste the output below.
Ionic:
ionic (Ionic CLI) : 4.0.0 (/usr/local/lib/node_modules/ionic)
Ionic Framework : @ionic/angular 4.0.0-beta.0
@angular-devkit/core : 0.7.0-rc.3
@angular-devkit/schematics : 0.7.0-rc.3
@angular/cli : 6.0.8
@ionic/ng-toolkit : 1.0.0
@ionic/schematics-angular : 1.0.0
System:
NodeJS : v10.6.0 (/usr/local/bin/node)
npm : 6.1.0
OS : macOS High Sierra
Describe the Bug
Trying to have an infinite scroll along with virtual scroll. After loading additional data, the virtual scrol is unable to scroll further and it stops with the initially loaded data. new data is not getting appended. Tried the same code without virtual scroll, it worked as expected.
Steps to Reproduce
Related Code
<ion-content padding>
<ion-virtual-scroll [items]="data" approxItemHeight="320px">
<ion-card *virtualItem="let item; let itemBounds = bounds;">
<ion-card-header>
<ion-card-title>{{ item }}</ion-card-title>
</ion-card-header>
</ion-card>
</ion-virtual-scroll>
<ion-infinite-scroll (ionInfinite)="doInfinite($event)">
<ion-infinite-scroll-content></ion-infinite-scroll-content>
</ion-infinite-scroll>
</ion-content>
Angular code
import { Component,ViewChild } from '@angular/core';
import {InfiniteScroll} from '@ionic/angular'
export class HomePage {
@ViewChild(InfiniteScroll) infiniteScroll: InfiniteScroll;
data = [];
doInfinite(event) {
console.log("loadData came");
setTimeout(function() {
let start = this.data.length;
let end = this.data.length + 10 ;
console.log("start: ",start,"end: ",end);
for(let i=start;i<end;i++){
this.data.push(i+1);
}
console.log('Done');
event.target.complete();
}.bind(this), 2000);
}
}
Expected Behavior
expected scrolling with new appended items.
Additional Context
List any other information that is relevant to your issue. Stack traces, related issues, suggestions on how to fix, Stack Overflow links, forum links, screenshots, OS if applicable, etc.
It seems like VirtualScroll doesn't currently update the height of the virtual list when the data set is changed, hence no ability to scroll beyond the initial data set. This is a virtual scroll specific problem and not related to infinite scroll or the combination.
To try it you can just create a simple array with enough items to fill more than the screen height, display it as a virtual scroll list and on a timer add new items to the end of the array. You can't scroll past more than the height of the original items.
@manucorporat this is still present in Beta12
From what I can tell this is still an issue.
I fetch the initial data and everything loads properly, once scrolled to the bottom I see the infinite scroll loader appearing and another request fires off to the api and gets more items. They are pushed to my items array but the virtualscroll does not update.
I've slightly modified above code and its working fine for me:
checkEnd()
on IonVirtualScroll element after new data has been pushedimport { Component, ViewChild } from '@angular/core';
import { IonInfiniteScroll, IonVirtualScroll } from '@ionic/angular';
@Component({
selector: 'app-home',
template: `
<ion-content padding>
<ion-virtual-scroll [items]="data" approxItemHeight="320px">
<ion-card *virtualItem="let item; let itemBounds = bounds;">
<ion-card-header>
<ion-card-title>{{ item }}</ion-card-title>
</ion-card-header>
</ion-card>
</ion-virtual-scroll>
<ion-infinite-scroll (ionInfinite)="doInfinite($event)">
<ion-infinite-scroll-content></ion-infinite-scroll-content>
</ion-infinite-scroll>
</ion-content>
`
})
export class HomePage {
@ViewChild(IonInfiniteScroll) infiniteScroll: IonInfiniteScroll;
@ViewChild(IonVirtualScroll) virtualScroll: IonVirtualScroll;
data = [];
constructor( ) {
// prefill list with data
this.doInfinite();
}
doInfinite(event) {
console.log('loadData came');
setTimeout(() => {
const start = this.data.length;
const end = this.data.length + 20;
console.log('start: ', start, 'end: ', end);
for (let i = start; i < end; i++) {
this.data.push(i + 1);
}
console.log('Done', this.data);
this.virtualScroll.checkEnd();
this.infiniteScroll.complete();
}, 2000);
}
}
@felly your code should be the example text in the docs it works well.
Did something change?
I tried to use this.virtualScroll.checkEnd(); but with no luck.
Fortunately there is no need for that.
I have this in my component:
`
{{ item.first_name }} {{ item.middle_name }} {{ item.last_name }}
<ion-infinite-scroll threshold="100px" (ionInfinite)="loadData($event)">
<ion-infinite-scroll-content
loadingSpinner="bubbles"
loadingText="Loading more data...">
</ion-infinite-scroll-content>
</ion-infinite-scroll>
</ion-card-content>
`
I am using the async pipe because the items are loaded from NgRx store like this: this.loadedPatients$ = this.store.pipe(select(fromPatient.getAllPatients));
Data is loaded like this:
loadData(event) {
this.store.dispatch(PatientsActions.loadMorePatients({
sort: 'first_name.middle_name.last_name',
order: 'ASC',
limit: 100,
deleted: this.toShow,
filter: this.filterValue ? this.filterValue : null,
event: event,
}));
}
where 'event' is the infinite scroll event and I am passing it to the Effect so I can call .complete() there:
`loadMore$ = createEffect(() =>
this.actions$.pipe(
ofType(PatientsActions.loadMorePatients),
withLatestFrom(
this.store.select(fromPatient.getPagination),
this.store.select(fromPatient.getAllPatients)
),
exhaustMap(([action, pagination, patents]) => {
if (action.event) {
action.event.target.complete();
if (patents.length === pagination.rowCount) {
action.event.target.disabled = true;
}
}
const options = {
...action,
page: pagination.page + 1
};
return this.patientsService
.fetchPatients({ ...options })
.pipe(
map((result) => PatientsActions.LoadMorePatientsSuccess({ patients: result.patients, pagination: result.pagination })),
catchError((err) => of(PatientsActions.LoadPatientsFail({ err: err })))
);
})
)
);`
and that's basically it. It works as intended but when I try to pass the virtual scroll element and call this.virtualScroll.checkEnd(); in the effect (not with this.virtualSroll ofcouce) there are all kinds of errors...
EDIT: I figured out that when I use the virtualScroll element outside of the component it gives the errors. Unlike the infinite scroll witch works fine...
If your have an async call back remove any timers and use this.virtualScroll.checkEnd() inside an async/await function.
Most helpful comment
I've slightly modified above code and its working fine for me:
checkEnd()
on IonVirtualScroll element after new data has been pushed