PrimeVue DataTable Virtual Scroller Resetting Scroll position on data change

290 views Asked by At

I'm having an issue where the scroll position resets on the data table but not on the virtual scroller component.

Every time you scroll to the fetchNextPage threshold, it resets the scroll position to 0, top of the virtual list. However on the virtual scroll component this doesn't occur. What could be triggering that? I want it to hold its scroll position.

enter image description here

const loadMore = (e: VirtualScrollerLazyEvent) => {
if (!logEvents || !logEvents.value) return;
console.log(`loadMore ${e.first} ${e.last} ${logEvents.value?.pages.length}`);
if (e.last > logEvents.value?.pages.length - 20) {
    console.log("fetchNextPage");
    fetchNextPage();
}

Virtual Scroller Code:

<VirtualScroller :items="logEvents?.pages" :loading="isLoading || isFetchingNextPage" :item-size="50"
        :showLoader=true class="border-1 surface-border border-round" style="width: 200px; height: 500px" lazy
        v-on:lazy-load="loadMore">
        <template v-slot:item="{ item, options }">
            <div :class="['flex align-items-center p-2', { 'surface-hover': options.odd }]" style="height: 50px">
                {{ options.index }} - {{ item.objectName }}</div>
        </template>
        <template v-slot:loader="{ options }">
            <div :class="['flex align-items-center p-2', { 'surface-hover': options.odd }]" style="height: 50px">
                <Skeleton :width="options.even ? '60%' : '50%'" height="1.3rem" />
            </div>
        </template>

Data Table Code:

<DataTable :value="logEvents?.pages" :loading="isLoading || isFetchingNextPage" scrollable scrollHeight="500px"
        tableStyle="min-width: 50rem" :virtualScrollerOptions="{
            lazy: true,
            onLazyLoad: loadMore,
            itemSize: 50,
        }">
        <Column field="objectName" sortable header="Object" style="height:50px">
            <template #body="{ data, index }">
                <span>{{ index }} : {{ data.objectName }}</span>
            </template>
            <template #loading>
                <div class="flex align-items-center" :style="{ height: '50px', 'flex-grow': '1', overflow: 'hidden' }">
                    <Skeleton width="60%" height="1rem" />
                </div>
            </template>
        </Column>
    </DataTable>

Code Sandbox

1

There are 1 answers

1
Igor Bezhevets On

Probably will not fix issue, that you're looking for, but partially will answer question. According to primevue example you should pre-fill table with large dataset you assume your logs will become in the end.

const logEventsWithPlaceholders = computed(() => {
  const blankLogs = Array.from({ length: 1000 })

  return [
    ...(logEvents?.value?.pages || []),
    ...blankLogs.slice(logEvents?.value?.pages.length)
  ]
})

And point your datatable to it:

 <DataTable
  :value="logEventsWithPlaceholders"

So now, when scrolling gently position won't be reset anymore. Its not suitable for clean lazy loading thou. If you grap scrollbar and pull it to the middle of the table (position ±500) loading will become broken. Primevue assume you should implement pagination based on scroll position (first and last properties accordingly) and your backend should support such pagination. I was struggling here as well and couldn't make it work.