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

Use UTable with paginated data, which comes from API #3776

Closed
ahoiroman opened this issue Apr 2, 2025 · 3 comments
Closed

Use UTable with paginated data, which comes from API #3776

ahoiroman opened this issue Apr 2, 2025 · 3 comments
Labels
question Further information is requested v3 #1289

Comments

@ahoiroman
Copy link

Description

Hi there,

I'd like to know, how to deal with paginated data that comes from the used API, e.g. a Laravel resource response.

{
  "current_page": 1,
  "data": [
    {
      "id": "1",
      "name": "Foo",
      "created_at": "2025-04-01T11:46:21+00:00"
    },
    {
      "id": "2",
      "name": "Bar",
      "created_at": "2025-04-01T11:46:21+00:00"
    },
  ],
  "first_page_url": "https:\/\/fanyv88.com:443\/https\/api.example.test\/test?page%5Bsize%5D=30&page%5Bnumber%5D=1",
  "from": 1,
  "last_page": 14,
  "last_page_url": "https:\/\/fanyv88.com:443\/https\/api.example.test\/test?page%5Bsize%5D=30&page%5Bnumber%5D=14",
  "links": [
    {
      "url": null,
      "label": "« Previous",
      "active": false
    },
    {
      "url": "https:\/\/fanyv88.com:443\/https\/api.example.test\/test?page%5Bsize%5D=30&page%5Bnumber%5D=1",
      "label": "1",
      "active": true
    },
    {
      "url": "https:\/\/fanyv88.com:443\/https\/api.example.test\/test?page%5Bsize%5D=30&page%5Bnumber%5D=2",
      "label": "2",
      "active": false
    },
    {
      "url": "https:\/\/fanyv88.com:443\/https\/api.example.test\/test?page%5Bsize%5D=30&page%5Bnumber%5D=3",
      "label": "3",
      "active": false
    },
    {
      "url": "https:\/\/fanyv88.com:443\/https\/api.example.test\/test?page%5Bsize%5D=30&page%5Bnumber%5D=4",
      "label": "4",
      "active": false
    },
    {
      "url": "https:\/\/fanyv88.com:443\/https\/api.example.test\/test?page%5Bsize%5D=30&page%5Bnumber%5D=5",
      "label": "5",
      "active": false
    },
    {
      "url": "https:\/\/fanyv88.com:443\/https\/api.example.test\/test?page%5Bsize%5D=30&page%5Bnumber%5D=6",
      "label": "6",
      "active": false
    },
    {
      "url": "https:\/\/fanyv88.com:443\/https\/api.example.test\/test?page%5Bsize%5D=30&page%5Bnumber%5D=7",
      "label": "7",
      "active": false
    },
    {
      "url": "https:\/\/fanyv88.com:443\/https\/api.example.test\/test?page%5Bsize%5D=30&page%5Bnumber%5D=8",
      "label": "8",
      "active": false
    },
    {
      "url": "https:\/\/fanyv88.com:443\/https\/api.example.test\/test?page%5Bsize%5D=30&page%5Bnumber%5D=9",
      "label": "9",
      "active": false
    },
    {
      "url": "https:\/\/fanyv88.com:443\/https\/api.example.test\/test?page%5Bsize%5D=30&page%5Bnumber%5D=10",
      "label": "10",
      "active": false
    },
    {
      "url": null,
      "label": "...",
      "active": false
    },
    {
      "url": "https:\/\/fanyv88.com:443\/https\/api.example.test\/test?page%5Bsize%5D=30&page%5Bnumber%5D=13",
      "label": "13",
      "active": false
    },
    {
      "url": "https:\/\/fanyv88.com:443\/https\/api.example.test\/test?page%5Bsize%5D=30&page%5Bnumber%5D=14",
      "label": "14",
      "active": false
    },
    {
      "url": "https:\/\/fanyv88.com:443\/https\/api.example.test\/test?page%5Bsize%5D=30&page%5Bnumber%5D=2",
      "label": "Next »",
      "active": false
    }
  ],
  "next_page_url": "https:\/\/fanyv88.com:443\/https\/api.example.test\/test?page%5Bsize%5D=30&page%5Bnumber%5D=2",
  "path": "https:\/\/fanyv88.com:443\/https\/api.example.test\/test",
  "per_page": 30,
  "prev_page_url": null,
  "to": 30,
  "total": 394
}

I am a bit intimidated by the TanStack API.

@ahoiroman ahoiroman added question Further information is requested v3 #1289 labels Apr 2, 2025
@EvanSchleret
Copy link

Hi, here's a component that I wrote to manage pagination (I also use a Laravel API as backend).

<script lang="ts" setup>
import type { Meta } from '~/types'

const props = defineProps<{
    meta: Meta
}>()

const page = defineModel('page', {
    type: Number,
    default: () => 1
})
</script>

<template>
    <div class="w-full flex items-center justify-between py-3.5">
        <UPagination
            v-model:page="page"
            size="sm"
            :items-per-page="props.meta.per_page ?? 1"
            :total="props.meta.total ?? 0"
        />

        <UBadge :label="`${props.meta.total ?? 0} enregistrement${props.meta.total === 0 ? '' : 's'}`" />
    </div>
</template>
// Meta interface
export interface Meta {
    current_page: number
    from: number
    last_page: number
    per_page: number
    to: number
    total: number
}

On my pages, I use my pagination component like that

<AppTablePagination
    :objects="records?.data.data ?? []"
    :meta="records.data.meta"
    :page="page"
    @update:page="(event: number) => {
        page = event
        router.push({ query: { ...route.query, page: event }, replace: true })
        refresh()
    }"
/>

Hope it could help you

@ahoiroman
Copy link
Author

Thanks!

I will try that. Bc I am on mobile at the moment, please excuse that I cannot test it just now.

One question remains: On the actual table, you are not using v-model:pagination and the pagination-options at all, right?

@ahoiroman
Copy link
Author

I got a first working example based on docs and your example.

In the table's component:

<UTable
    ref="table"
    v-model:pagination="pagination"
    :data="data"
    :columns="columns"
/>

// ...
const table = useTemplateRef('table')

defineExpose({
  table
})

const pagination = ref({
  pageIndex: 1,
  pageSize: 15,
  rowCount: 0
})

watchEffect(() => pagination.value.rowCount = data.value?.total || 0)

This exposes the table ref, which I can use in a different component like this:

<MyTable ref="myTable" />

<UPagination
  v-if="myTable?.table?.tableApi?.getState().pagination.pageSize"
  :page="(myTable?.table?.tableApi?.getState().pagination.pageIndex || 1)"
  :default-page="(myTable?.table?.tableApi?.getState().pagination.pageIndex || 1)"
  :items-per-page="myTable?.table?.tableApi?.getState().pagination.pageSize"
  :total="myTable?.table?.tableApi?.getState().pagination.rowCount"
  @update:page="(p) => myTable?.table?.tableApi?.setPageIndex(p)"
/>

// ...

const myTable = ref()

This might not be the final version, but it is working for now. Thanks a lot for your helpful example.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested v3 #1289
Projects
None yet
Development

No branches or pull requests

2 participants