I have an ionic angular application which uses an infinite scroll. When resetting the initial data to fetch updates, or to the fetch a change in language and to retrieve data in another language, the infinite scroll is broken.
ngOnInit() {
this.languageSubscription = this.userService.getLanguage().subscribe(lang => {
this.language = lang;
this.resetElements();
});
}
// Breaks the infinite scroll
resetElements() {
this.page = 1;
this.elements = [];
this.fetchElements();
}
fetchElements(event?: any) {
this.elementsSubscription = this.elementService.getElements(this.language, this.page, this.limit)
.subscribe(res => {
this.elements = [...this.elements, ...res.body.data];
this.totalPages = res.body.totalPages;
this.page++;
if (event) event.target.complete();
});
}
loadMore(event: any) {
if (this.page <= this.totalPages) {
this.fetchElements(event);
}
else {
event.target.disabled = true;
}
}
handleRefresh(event: any) {
this.resetElements();
event.target.complete();
}
Infinite scroll html:
<ion-infinite-scroll #infiniteScroll (ionInfinite)="loadMore($event)">
<ion-infinite-scroll-content loadingSpinner="bubbles">
</ion-infinite-scroll-content>
</ion-infinite-scroll>
I tried to re-enable the infinite scroll with a Viewchild, but that didn't work.
@ViewChild('infiniteScroll') infiniteScroll: IonInfiniteScroll;
resetElements() {
this.page = 1;
this.elements = [];
if (this.infiniteScroll) {
this.infiniteScroll.disabled = false;
}
this.fetchElements();
}
Apparently, according to the Ionic docs, the complete() method is async.
For the ionInfinite handler:
Call
complete()
within theionInfinite
output event handler when your async operation has completed. For example, theloading
state is while the app is performing an asynchronous operation, such as receiving more data from an AJAX request to add more items to a data list. Once the data has been received and UI updated, you then call this method to signify that the loading has completed. This method will change the infinite scroll's state fromloading
toenabled
.
For the ionRefresh handler:
Emitted when the user lets go of the content and has pulled down further than the
pullMin
or pulls the content down and exceeds the pullMax. Updates the refresher state torefreshing
. Thecomplete()
method should be called when the async operation has completed.
So I had to make all my complete() calls async:
fetchElements(event?: any) {
this.elementsSubscription = this.elementService.getElements(this.language, this.page, this.limit)
.subscribe(async res => {
this.elements = [...this.elements, ...res.body.data];
this.totalPages = res.body.totalPages;
this.page++;
if (event)
await event.target.complete();
});
}
async handleRefresh(event: any) {
this.resetElements();
await event.target.complete();
}
async loadMore(event: any) {
if (this.page <= this.totalPages) {
this.fetchElements(event);
}
else {
await event.target.complete();
event.target.disabled = true;
}
}