Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug Report][3.3.11] VDataTable - Unable to set initial page #17966

Closed
hackel opened this issue Aug 4, 2023 · 17 comments · Fixed by #19542 or con-cis/mc-docu#48 · May be fixed by mygivvara/codex#5 or aurelienfvre/sae401#1
Closed

[Bug Report][3.3.11] VDataTable - Unable to set initial page #17966

hackel opened this issue Aug 4, 2023 · 17 comments · Fixed by #19542 or con-cis/mc-docu#48 · May be fixed by mygivvara/codex#5 or aurelienfvre/sae401#1
Labels
C: VDataTableServer help wanted We are looking for community help T: bug Functionality that does not work as intended/expected
Milestone

Comments

@hackel
Copy link

hackel commented Aug 4, 2023

Environment

Vuetify Version: 3.3.11
Vue Version: 3.3.4
Browsers: Firefox 117.0
OS: Linux x86_64

Steps to reproduce

Set the page prop to something other than 1. (e.g. from a URL query parameter)

Expected Behavior

Table displays the given page of the table.

Actual Behavior

The page prop is always changed back to 1 on load.

Reproduction Link

https://play.vuetifyjs.com/#...

@websitevirtuoso
Copy link
Contributor

Yes I can confirm. Issue persist and datatable reset it always to 1 on mounting. I think this is easy fix

@nekosaur
Copy link
Member

nekosaur commented Oct 2, 2023

Set the initial value of items-length prop to x * items-per-page where x is the page you want to start on.

I'm not sure if we should call this a bug or not. Maaybe we'd want different behavior in -server variant. I'll keep this open for now.

@nekosaur nekosaur added maybe Functionality that we are considering C: VDataTableServer and removed S: triage labels Oct 2, 2023
@HristoAntov
Copy link

HristoAntov commented Dec 2, 2023

I can confirm that this is a bug and it's present at least from August this year. The workaround with the items-length prop not only doesn't fix anything, but completely messes up the pagination behavior

It practically makes using the table pagination in sync with url parameters impossible.

@K4GR
Copy link

K4GR commented Dec 18, 2023

I can offer a temporary and very strange but working solution. If you add to your table
@update:page="() => {}"
then everything starts working correctly

playground

@KozakoPolako
Copy link

vuetify 3.4.9 and still not fixed 😒 btw U can bring back options prop to VDataTable. Now with only update:options event is confusing, especially when U migrate from vue 2

@KozakoPolako
Copy link

I can offer a temporary and very strange but working solution. If you add to your table @update:page="() => {}" then everything starts working correctly

playground

Except of page change, unfortunately

@Melvinvmegen
Copy link

I really appreciate your work but i have to say I really don't understand how this is labeled as maybe. How are we supposed to save the pagination in the navigation if the table keeps resetting to the first page?

@websitevirtuoso
Copy link
Contributor

websitevirtuoso commented Jan 16, 2024

we need to fix it to implement this ability.
Any help and PR are welcome

@naglafar
Copy link

naglafar commented Jan 30, 2024

+1 on this.

I cant initialise a table on any page other than 1.

Workaround: Don't render the table until you have loaded the data. Use a skeleton load while you wait.

@klondikemarlen
Copy link

klondikemarlen commented Mar 13, 2024

+1 on this.

I cant initialise a table on any page other than 1.

Workaround: Don't render the table until you have loaded the data. Use a skeleton load while you wait.

Thanks @naglafar. I can confirm that, "delaying render until after loading completes", works for me.

<template>
  <v-skeleton-loader
    v-if="isLoading"
    type="table"
  />
  <v-data-table-server
    v-else
    v-model:items-per-page="itemsPerPage"
    v-model:page="page"
    :headers="headers"
    :items="items"
    :items-length="totalCount"
    :loading="isLoading"
  />
</template>

Assuming items are loaded like

async function fetch() {
  isLoading.value = true
  try {
     items.value = await fetchSomeItems()
  } finally {
     isLoading.value = false
  }
}

where isLoading resolves after items have fully loaded.

EDIT: see icefoganalytics/internal-data-portal@fe84016 for full example.

klondikemarlen added a commit to icefoganalytics/internal-data-portal that referenced this issue Mar 13, 2024
NOTE: Use of v-skeleton-loader. If you don't do this the v-data-table-server component will reset the page value on load. See vuetifyjs/vuetify#17966
@klondikemarlen
Copy link

Is this just a bug in

?

Should it be something like page.value = page.value || 1?

klondikemarlen added a commit to icefoganalytics/internal-data-portal that referenced this issue Mar 13, 2024
NOTE: Use of v-skeleton-loader. If you don't do this the v-data-table-server component will reset the page value on load. See vuetifyjs/vuetify#17966

The UI related to this is pretty bad, as it causes flicker, but at least the but is avoided.
klondikemarlen added a commit to icefoganalytics/internal-data-portal that referenced this issue Mar 13, 2024
Solution: ignore page change while loading. This is a better fix for:
> Use of v-skeleton-loader. If you don't do this the v-data-table-server component will reset the page value on load. See vuetifyjs/vuetify#17966
@klondikemarlen
Copy link

I've found a work-around for the flicker introduced by using v-if with a skeleton loader.
You can ignore updates to page while isLoading is true, assuming that isLoading resolves after items have been updated.

<template>
  <v-data-table-server
    v-model:items-per-page="itemsPerPage"
    :page="page"
    :headers="headers"
    :items="items"
    :items-length="totalCount"
    :loading="isLoading"
    @update:page="updatePage"
  />
</template>

<script setup lang="ts">
// ... other code and variable setup

function updatePage(newPage: number) {
  if (isLoading.value) return

  page.value = newPage
}

async function fetch() {
  isLoading.value = true
  try {
    items.value = await fetchSomeItems()
  } finally {
    isLoading.value = false
  }
}
</script>

See icefoganalytics/internal-data-portal@49fbafc

klondikemarlen added a commit to icefoganalytics/internal-data-portal that referenced this issue Mar 13, 2024
Solution: ignore page change while loading. This is a better work-around for:
> Use of v-skeleton-loader. If you don't do this the v-data-table-server component will reset the page value on load. See vuetifyjs/vuetify#17966
webdevnerdstuff added a commit to webdevnerdstuff/vuetify that referenced this issue Apr 4, 2024
johnleider added a commit that referenced this issue Apr 9, 2024
@Ribeiro-Tiago
Copy link

Still have this issue as of 3.6.9

@johnleider johnleider reopened this Jun 17, 2024
@johnleider johnleider removed maybe Functionality that we are considering S: triage labels Jun 17, 2024
@johnleider johnleider added the T: bug Functionality that does not work as intended/expected label Jun 17, 2024
@matejbujnak
Copy link

matejbujnak commented Jun 25, 2024

I've implemented a solution where an initializing value is used to bypass the first @update:options="updateOptions" event. This prevents unintended modifications during the initial table setup.

<script setup>
import { ref } from 'vue';

const initialLoad = ref(true); // Flag to indicate initial load

async function updateOptions(params = {}) {
  if (initialLoad.value) { 
    initialLoad.value = false; // Disable after initial update
    params.page = getPage();   // Apply initial page setting
  }
  // ... (Rest of your update logic)
}
</script>

<template>
  <v-data-table 
    v-model:page="page"
    @update:options="updateOptions"
    ...>
    </v-data-table>
</template>

@olivierpoisson
Copy link

olivierpoisson commented Jul 16, 2024

One way that could work for some people is to use a watcher instead of listening to the @update:options event. What I mean:

<v-data-table-server
    v-model:page="options.page"
    v-model:items-per-page="options.itemsPerPage"
/>

const options = ref({
  page: 1,
  itemsPerPage: 10,
});

watch(options, value => {
    // Fetch your data.
  },
  { deep: true }
)

This allows you to check the query in onMounted() and changing the options ref once, so that you will only make 1 fetch call

onMounted(() => {
    // Pseudo code. This will trigger the watcher only once
    options.value = {
        page: query.page,
        itemsPerPage: query.itemsPerPage
    }
});

Here is a playground demonstrating what I mean: Playground

@bierik
Copy link

bierik commented Oct 9, 2024

Still having this issue. What is the status here? @webdevnerdstuff's PR does not seem to resolve the issue as far as I can tell.

@blakegearin
Copy link

blakegearin commented Nov 15, 2024

Still having this issue on 3.7.3

The only reliable way I'm able to avoid this bug seems to be setting a default of null instead of a number value.

<template>
  <v-data-table-server
    :items-length="itemsLength"
    :page="page"
  >
  </v-data-table-server>
</template>

<script setup>
import { ref } from 'vue';

const itemsLength = ref(null);
const page = ref(1);
</script>

I believe this works because when items length is null no comparison to the page number can be made, so the page number's value remains intact until items length is populated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment