I want to hide or show elements when there is or there isn't a scrollbar on ion-content. More specifically, I want to show a button (to load more items in a list) when there's no scrollbar and hide it where there is a scrollbar (so the loading of more items is done by ion-infinite-scroll).
My Ionic app will also be deployed to the desktop so users with large screens won't initially see a scrollbar and thus ion-infinite-scroll won't be triggered.
Here's a demo that showcases the issue:
home.page.html
<ion-header>
<ion-toolbar>
<ion-title>
Ionic header
</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<div class="ion-padding">
<p *ngFor="let item of itemList">{{ item }}</p>
<!-- How to hide this button when ion-content has a scrollbar? -->
<!-- *ngIf="???" -->
<ion-button (click)="incrementItemList(5)">Load more items</ion-button>
</div>
<ion-infinite-scroll (ionInfinite)="loadMoreItems($event)">
<ion-infinite-scroll-content loadingSpinner="crescent"></ion-infinite-scroll-content>
</ion-infinite-scroll>
</ion-content>
<ion-footer>
<ion-toolbar>
<ion-title>
Ionic footer
</ion-title>
</ion-toolbar>
</ion-footer>
home.page.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage {
itemList: string[] = [];
constructor() {}
ionViewWillEnter() {
this.incrementItemList(5);
}
incrementItemList(times: number) {
for (let i = 1; i <= times; i++) {
this.itemList.push(`Lorem ipsum dolor sit amet consectetur adipisicing elit. Quia placeat nam sapiente iusto eligendi`);
}
}
loadMoreItems(event: any) {
setTimeout(() => {
this.incrementItemList(15);
event.target.complete();
}, 1000);
}
}
I'm using Ionic 4.5.0 + Angular.
I have tried using getScrollElement, scrollHeight, clientHeight, offsetHeight, but with no success.
Any ideas?
With the help of rtpHarry's post (thanks!), I finally came up with a proper solution for this use case:
home.page.html
<ion-content>
<div class="ion-padding">
<p *ngFor="let item of itemList">{{ item }}</p>
<!--
'*ngIf' removes the button from the DOM and changes the size of 'ion-content' which
is problematic in some scenarios so I toggle the visibility CSS property instead
-->
<ion-button [style.visibility]="hasScrollbar ? 'hidden' : 'visible'" (click)="incrementItemList(5)">Load more items</ion-button>
</div>
<ion-infinite-scroll (ionInfinite)="loadMoreItems($event)">
<ion-infinite-scroll-content loadingSpinner="crescent"></ion-infinite-scroll-content>
</ion-infinite-scroll>
</ion-content>
home.page.ts
import { Component, ViewChild, HostListener } from '@angular/core';
import { IonContent } from '@ionic/angular';
@Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage {
hasScrollbar = false;
itemList: string[] = [];
@ViewChild(IonContent, {static: false}) private content: IonContent;
// checks if there's a scrollbar when the user resizes the window or zooms in/out
@HostListener('window:resize', ['$event'])
onResize() {
this.checkForScrollbar();
}
constructor() {}
ionViewWillEnter() {
this.incrementItemList(5);
}
incrementItemList(times: number) {
for (let i = 1; i <= times; i++) {
this.itemList.push(`Lorem ipsum dolor sit amet consectetur adipisicing elit. Quia placeat nam sapiente iusto eligendi`);
}
this.checkForScrollbar();
}
loadMoreItems(event: any) {
setTimeout(() => {
this.incrementItemList(15);
event.target.complete();
}, 1000);
}
async checkForScrollbar() {
const scrollElement = await this.content.getScrollElement();
this.hasScrollbar = scrollElement.scrollHeight > scrollElement.clientHeight;
}
}