vuetifyjs / vuetify

🐉 Vue Component Framework
https://vuetifyjs.com
MIT License
39.64k stars 6.95k forks source link

[Feature Request] Change load status in v-infinite-scroll from parent component #19935

Open sanaderi opened 3 months ago

sanaderi commented 3 months ago

Problem to solve

I want connect v-infinite- loading to to some filter. such country and city.

If the user changes the filter and before that the loading has reached the empty state. It is no longer called by changing the filter of other pages

Proposed solution

I think we need a props to can change status programmatically

wisskirchenj commented 3 months ago

I just found, that after updating vuetify in my app, the infinite scroller no longer worked, when resetting a filter or on reload of table contents, as soon as it gets into the 'empty' state (scrolled to bottom of contents) before.

From the code change of v 3.6.4: VInfiniteScroll: do not emit load event if status is empty this behavior is understandable: As soons as the component gets into the 'empty' state, there is no way for it to get out of this state anymore.. The intersecting function returns on 'empty' and the setStatus-function further below is no longer reachable. This means, that scrolling can no longer trigger load-events - forever.

My app worked fine until v 3.6.3 - when reloading / resetting filter etc.

So I agree, that either

The 1st option would give more flexibility and may be more performant, than watching the item data - however, it needs extra handling in the parent component. But both options should work. I'd prefer the 1st one in fact.

also comp. issue #19909

tmichalski commented 1 month ago

In order to work my way around this issue, I saved the reference to the event handler done to a local variable so that I can reuse it later when I need to change the infinite scroll event state from "empty" to "ok".

For example (not tested code):

<template>
  <v-infinite-scroll :items="myItems" @load="loadMoreItems">
       ....
  </v-infinite-scroll>

   <v-btn @click="refreshItems">Refresh Items</v-btn>
</template>

Nothing to do on the component tag, just showing the below snippet for context.

<script setup lang="ts">
const myItems = ref<string[]>(['Hello', 'World']);
let infiniteScrollEvents: ((value: 'ok' | 'empty' | 'error') => void) | undefined;

function loadMoreItems({ done }: { done: (value: 'ok' | 'empty' | 'error') => void }): void {
     infiniteScrollEvents = done;
     myItems.value.push('Hola');
     myItems.value.push('Mundo');
     done('empty');
}

function refreshItems(): void {
    myItems.value = ['Hello', 'World'];
    if (infiniteScrollEvents) {
        infiniteScrollEvents('ok');
    }
}
</script>
  1. infiniteScrollEvents variable is declared to hold the reference to the infinite scroll event handler.
  2. Every time loadMoreItems is called, the done event handler is assigned to infiniteScrollEvents
  3. Reset the infinite scroll by calling infiniteScrollEvents('ok') in any function in your component.

While this is not runnable code, the main point is just grab a reference of done and you can interact with the VInfiniteScroll event internals. I was able to get around this limitation of infinite scroll using this technique.

wisskirchenj commented 1 month ago

In order to work my way around this issue, I saved the reference to the event handler done to a local variable so that I can reuse it later when I need to change the infinite scroll event state from "empty" to "ok". ...

THX! This is a great workaround for the time being - which I essentially now copied into my app too (I used a ref to store the "done callback" in my component). This enables me to bump to current Vuetify version again! However, I still hope this gets handled by the framework, as the component is just buggy IMHO... and the workaround is a smart "hack" that relies on component internals too...

maltalef101 commented 1 week ago

I agree with the previous response, as I also have this issue myself. The proposed workaround is useful, yes, but it's messy, and this doesn't seem a crazy of a scenario to me.