Skip to content

Commit

Permalink
feat(Table): extends core options and support other options like `pag…
Browse files Browse the repository at this point in the history
…ination` (#3177)

Co-authored-by: Sandros94 <[email protected]>
Co-authored-by: Benjamin Canac <[email protected]>
  • Loading branch information
3 people authored Feb 5, 2025
1 parent c5bb540 commit 4aa3179
Show file tree
Hide file tree
Showing 5 changed files with 306 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,6 @@ const columns: TableColumn<Payment>[] = [{
}
}]
const table = useTemplateRef('table')
const globalFilter = ref('45')
</script>

Expand Down
174 changes: 174 additions & 0 deletions docs/app/components/content/examples/table/TablePaginationExample.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
<script setup lang="ts">
import { getPaginationRowModel } from '@tanstack/vue-table'
import type { TableColumn } from '@nuxt/ui'
const table = useTemplateRef('table')
type Payment = {
id: string
date: string
email: string
amount: number
}
const data = ref<Payment[]>([{
id: '4600',
date: '2024-03-11T15:30:00',
email: '[email protected]',
amount: 594
}, {
id: '4599',
date: '2024-03-11T10:10:00',
email: '[email protected]',
amount: 276
}, {
id: '4598',
date: '2024-03-11T08:50:00',
email: '[email protected]',
amount: 315
}, {
id: '4597',
date: '2024-03-10T19:45:00',
email: '[email protected]',
amount: 529
}, {
id: '4596',
date: '2024-03-10T15:55:00',
email: '[email protected]',
amount: 639
}, {
id: '4595',
date: '2024-03-10T13:20:00',
email: '[email protected]',
amount: 428
}, {
id: '4594',
date: '2024-03-10T11:05:00',
email: '[email protected]',
amount: 673
}, {
id: '4593',
date: '2024-03-09T22:15:00',
email: '[email protected]',
amount: 382
}, {
id: '4592',
date: '2024-03-09T20:30:00',
email: '[email protected]',
amount: 547
}, {
id: '4591',
date: '2024-03-09T18:45:00',
email: '[email protected]',
amount: 291
}, {
id: '4590',
date: '2024-03-09T16:20:00',
email: '[email protected]',
amount: 624
}, {
id: '4589',
date: '2024-03-09T14:10:00',
email: '[email protected]',
amount: 438
}, {
id: '4588',
date: '2024-03-09T12:05:00',
email: '[email protected]',
amount: 583
}, {
id: '4587',
date: '2024-03-09T10:30:00',
email: '[email protected]',
amount: 347
}, {
id: '4586',
date: '2024-03-09T08:15:00',
email: '[email protected]',
amount: 692
}, {
id: '4585',
date: '2024-03-08T23:40:00',
email: '[email protected]',
amount: 419
}, {
id: '4584',
date: '2024-03-08T21:25:00',
email: '[email protected]',
amount: 563
}, {
id: '4583',
date: '2024-03-08T19:50:00',
email: '[email protected]',
amount: 328
}, {
id: '4582',
date: '2024-03-08T17:35:00',
email: '[email protected]',
amount: 647
}, {
id: '4581',
date: '2024-03-08T15:20:00',
email: '[email protected]',
amount: 482
}])
const columns: TableColumn<Payment>[] = [{
accessorKey: 'id',
header: '#',
cell: ({ row }) => `#${row.getValue('id')}`
}, {
accessorKey: 'date',
header: 'Date',
cell: ({ row }) => {
return new Date(row.getValue('date')).toLocaleString('en-US', {
day: 'numeric',
month: 'short',
hour: '2-digit',
minute: '2-digit',
hour12: false
})
}
}, {
accessorKey: 'email',
header: 'Email'
}, {
accessorKey: 'amount',
header: () => h('div', { class: 'text-right' }, 'Amount'),
cell: ({ row }) => {
const amount = Number.parseFloat(row.getValue('amount'))
const formatted = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'EUR'
}).format(amount)
return h('div', { class: 'text-right font-medium' }, formatted)
}
}]
const pagination = ref({
pageIndex: 0,
pageSize: 5
})
</script>

<template>
<div class="w-full space-y-4 pb-4">
<UTable
ref="table"
v-model:pagination="pagination"
:data="data"
:columns="columns"
:pagination-options="{
getPaginationRowModel: getPaginationRowModel()
}"
class="flex-1"
/>

<div class="flex justify-center border-t border-[var(--ui-border)] pt-4">
<UPagination
:default-page="(table?.tableApi?.getState().pagination.pageIndex || 0) + 1"
:items-per-page="table?.tableApi?.getState().pagination.pageSize"
:total="table?.tableApi?.getFilteredRowModel().rows.length"
@update:page="(p) => table?.tableApi?.setPageIndex(p - 1)"
/>
</div>
</div>
</template>
21 changes: 20 additions & 1 deletion docs/content/3.components/table.md
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ You can use the `column-pinning` prop to control the pinning state of the column

### With column visibility

You can add use [DropdownMenu](/components/dropdown-menu) component to toggle the visibility of the columns using the TanStack Table [Column Visibility APIs](https://tanstack.com/table/latest/docs/api/features/column-visibility).
You can use a [DropdownMenu](/components/dropdown-menu) component to toggle the visibility of the columns using the TanStack Table [Column Visibility APIs](https://tanstack.com/table/latest/docs/api/features/column-visibility).

::component-example
---
Expand Down Expand Up @@ -391,6 +391,25 @@ class: '!p-0'
You can use the `global-filter` prop to control the global filter state (can be binded with `v-model`).
::

### With pagination

You can use a [Pagination](/components/pagination) component to control the pagination state using the [Pagination APIs](https://tanstack.com/table/latest/docs/api/features/pagination).

There are different pagination approaches as explained in [Pagination Guide](https://tanstack.com/table/latest/docs/guide/pagination#pagination-guide). In this example, we use client-side pagination so we need to manually pass `getPaginationRowModel()`{lang="ts-type"} function.

::component-example
---
prettier: true
collapse: true
name: 'table-pagination-example'
class: '!p-0'
---
::

::tip
You can use the `pagination` prop to control the pagination state (can be binded with `v-model`).
::

### With fetched data

You can fetch data from an API and use them in the Table.
Expand Down
18 changes: 14 additions & 4 deletions playground/app/pages/components/table.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { h, resolveComponent } from 'vue'
import { upperFirst } from 'scule'
import type { TableColumn } from '@nuxt/ui'
import { getPaginationRowModel } from '@tanstack/vue-table'
const UButton = resolveComponent('UButton')
const UCheckbox = resolveComponent('UCheckbox')
Expand Down Expand Up @@ -269,6 +270,11 @@ const columnPinning = ref({
right: ['actions']
})
const pagination = ref({
pageIndex: 0,
pageSize: 10
})
function randomize() {
data.value = [...data.value].sort(() => Math.random() - 0.5)
}
Expand Down Expand Up @@ -322,11 +328,15 @@ onMounted(() => {
:columns="columns"
:column-pinning="columnPinning"
:loading="loading"
sticky
:pagination="pagination"
:pagination-options="{
getPaginationRowModel: getPaginationRowModel()
}"
:ui="{
tr: 'divide-x divide-[var(--ui-border)]'
}"
class="border border-[var(--ui-border-accented)] rounded-[var(--ui-radius)] flex-1"
sticky
class="border border-[var(--ui-border-accented)] rounded-[var(--ui-radius)]"
>
<template #expanded="{ row }">
<pre>{{ row.original }}</pre>
Expand All @@ -339,7 +349,7 @@ onMounted(() => {
{{ table?.tableApi?.getFilteredRowModel().rows.length || 0 }} row(s) selected.
</div>

<!-- <div class="flex items-center gap-1.5">
<div class="flex items-center gap-1.5">
<UButton
color="neutral"
variant="outline"
Expand All @@ -356,7 +366,7 @@ onMounted(() => {
>
Next
</UButton>
</div> -->
</div>
</div>
</div>
</template>
Loading

0 comments on commit 4aa3179

Please sign in to comment.