Open ionitron-bot[bot] opened 6 years ago
Same problem here.
I have the same issue and I'm trying to solve it by detecting the scrollbar: https://forum.ionicframework.com/t/how-to-detect-if-ion-content-has-a-scrollbar/167840
This is still happening in ionic4 btw.
Solved by detecting the scrollbar and using, for example, a button as a fallback to load more items: https://stackoverflow.com/a/58579938/2892404
Posting a Vue/TypeScript wrapper component I made to implement the fix of automatically loading elements in until they fill the page height.
Includes some cruft like requiredType() and notNullOrUndefined(); in my own context these are convenience methods I import everywhere.
Had to use my own implementation of isInScroll() which adds up the height of the content's children; I found that otherwise the scrollHeight
of ion-content
would be locked to the clientHeight
so the condition would never trigger.
Also added an exists
prop. Could be replaced with v-if
but I wanted to emphasize that this thing needs to disappear when the complete set is fetched; otherwise you are open to a problem where scroll() will be called over and over if the complete list of results fails to cover the entire page.
<template>
<IonInfiniteScroll threshold="0" @ionInfinite="doScroll" v-if="exists">
<IonInfiniteScrollContent
loadingSpinner="bubbles"
loadingText="Loading…" />
</IonInfiniteScroll>
</template>
<script lang="ts">
import {defineComponent, onMounted, ref, onUpdated, onBeforeUnmount} from 'vue'
import {
IonInfiniteScroll,
IonInfiniteScrollContent
} from '@ionic/vue'
function isInScroll(element: HTMLElement) {
let childrenScrollHeight = 0
for (const child of element.childNodes) {
// @ts-ignore
childrenScrollHeight += child.scrollHeight || 0
}
return childrenScrollHeight > element.clientHeight
}
function requiredType<T>(
type: any
) {
return {
type: type as () => T,
required: true as true
}
}
function notNullOrUndefined<T>(t: T | undefined | null, errorMessage = "") {
if (t === undefined || t === null) {
throw new Error(errorMessage || "Value was null or undefined.");
}
else {
return t;
}
}
function wrapAsyncInInfiniteScroll<T>(fn: () => Promise<T>) {
return async function (e: { target: { complete: () => void } }) {
try {
await fn()
} finally {
e.target.complete()
}
}
}
export default defineComponent({
components: {
IonInfiniteScroll,
IonInfiniteScrollContent
},
props: {
exists: Boolean,
scroll: requiredType<() => Promise<any>>(Function)
},
setup(props) {
const isMounted = ref(false)
const loadUntilScrollable = async () => {
const mainPageElement = notNullOrUndefined(
document.querySelector('ion-content')
)
while (!isInScroll(mainPageElement) && isMounted.value) {
await props.scroll()
}
}
onMounted(
() => {
isMounted.value = true
loadUntilScrollable()
}
)
onUpdated(
loadUntilScrollable
)
onBeforeUnmount(
() => isMounted.value = false
)
const doScroll = wrapAsyncInInfiniteScroll(props.scroll)
return {
doScroll
}
}
})
</script>
<style scoped>
.infinite-loading {
background: rgba(255,255,255,.5);
padding: 1rem;
}
.infinite-loading {
margin-bottom: 0;
}
.infinite-scroll-content-md .infinite-loading-text {
color: #333
}
</style>
Short description of the problem:
The
ion-infinite-scroll
component works by listening for anonScroll
event. However, if the initial items loaded do not trigger such an event, then the ion-infinite-scroll will never trigger anionInfinite
callback, resulting in a broken page.What behavior are you expecting?
I would expect that, when the
InfiniteScroll
object is enabled (listener added), and also after anyionInfinite.complete()
call, that the currentonScroll
check would be manually run in order to see if anotherionInfinite
event needs to be triggered immediately.Currently, to workaround this, I have two lines executed after both the initial page loading and after each
ionInfiniteEvent.complete()
call:Steps to reproduce:
ionInfinite
never gets triggered.Which Ionic Version? 2.0 RC2