docs: expanding table in data-table component
This commit is contained in:
parent
548aa7ed4d
commit
8444039cb3
|
|
@ -889,6 +889,218 @@ You can show the number of selected rows using the `table.getFilteredSelectedRow
|
|||
|
||||
</Steps>
|
||||
|
||||
<Steps>
|
||||
|
||||
## Expanding
|
||||
|
||||
Let's make rows expandable.
|
||||
|
||||
### Update `<DataTable>`
|
||||
|
||||
```vue:line-numbers {7,30,43,52,57,63,103-116}
|
||||
<script setup lang="ts" generic="TData, TValue">
|
||||
import type {
|
||||
ColumnDef,
|
||||
ColumnFiltersState,
|
||||
SortingState,
|
||||
VisibilityState,
|
||||
ExpandedState,
|
||||
} from '@tanstack/vue-table'
|
||||
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuCheckboxItem,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuTrigger,
|
||||
} from '@/components/ui/dropdown-menu'
|
||||
|
||||
import { valueUpdater } from '@/lib/utils'
|
||||
|
||||
import { ArrowUpDown, ChevronDown } from 'lucide-vue-next'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { h, ref } from 'vue'
|
||||
|
||||
import {
|
||||
FlexRender,
|
||||
getCoreRowModel,
|
||||
getPaginationRowModel,
|
||||
getFilteredRowModel,
|
||||
getSortedRowModel,
|
||||
getExpandedRowModel,
|
||||
useVueTable,
|
||||
} from "@tanstack/vue-table"
|
||||
|
||||
const props = defineProps<{
|
||||
columns: ColumnDef<TData, TValue>[]
|
||||
data: TData[]
|
||||
}>()
|
||||
|
||||
const sorting = ref<SortingState>([])
|
||||
const columnFilters = ref<ColumnFiltersState>([])
|
||||
const columnVisibility = ref<VisibilityState>({})
|
||||
const rowSelection = ref({})
|
||||
const expanded = ref<ExpandedState>({})
|
||||
|
||||
const table = useVueTable({
|
||||
get data() { return props.data },
|
||||
get columns() { return props.columns },
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
getPaginationRowModel: getPaginationRowModel(),
|
||||
getSortedRowModel: getSortedRowModel(),
|
||||
getFilteredRowModel: getFilteredRowModel(),
|
||||
getExpandedRowModel: getExpandedRowModel(),
|
||||
onSortingChange: updaterOrValue => valueUpdater(updaterOrValue, sorting),
|
||||
onColumnFiltersChange: updaterOrValue => valueUpdater(updaterOrValue, columnFilters),
|
||||
onColumnVisibilityChange: updaterOrValue => valueUpdater(updaterOrValue, columnVisibility),
|
||||
onRowSelectionChange: updaterOrValue => valueUpdater(updaterOrValue, rowSelection),
|
||||
onExpandedChange: updaterOrValue => valueUpdater(updaterOrValue, expanded),
|
||||
state: {
|
||||
get sorting() { return sorting.value },
|
||||
get columnFilters() { return columnFilters.value },
|
||||
get columnVisibility() { return columnVisibility.value },
|
||||
get rowSelection() { return rowSelection.value },
|
||||
get expanded() { return expanded.value },
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div class="flex items-center py-4">
|
||||
<Input class="max-w-sm" placeholder="Filter emails..."
|
||||
:model-value="table.getColumn('email')?.getFilterValue() as string"
|
||||
@update:model-value=" table.getColumn('email')?.setFilterValue($event)" />
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger as-child>
|
||||
<Button variant="outline" class="ml-auto">
|
||||
Columns
|
||||
<ChevronDown class="w-4 h-4 ml-2" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuCheckboxItem
|
||||
v-for="column in table.getAllColumns().filter((column) => column.getCanHide())" :key="column.id"
|
||||
class="capitalize" :checked="column.getIsVisible()" @update:checked="(value) => {
|
||||
column.toggleVisibility(!!value)
|
||||
}">
|
||||
{{ column.id }}
|
||||
</DropdownMenuCheckboxItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
<div class="border rounded-md">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow v-for="headerGroup in table.getHeaderGroups()" :key="headerGroup.id">
|
||||
<TableHead v-for="header in headerGroup.headers" :key="header.id">
|
||||
<FlexRender v-if="!header.isPlaceholder" :render="header.column.columnDef.header"
|
||||
:props="header.getContext()" />
|
||||
</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
<template v-if="table.getRowModel().rows?.length">
|
||||
<template v-for="row in table.getRowModel().rows" :key="row.id">
|
||||
<TableRow :data-state="row.getIsSelected() ? 'selected' : undefined">
|
||||
<TableCell v-for="cell in row.getVisibleCells()" :key="cell.id">
|
||||
<FlexRender :render="cell.column.columnDef.cell" :props="cell.getContext()" />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow v-if="row.getIsExpanded()">
|
||||
<TableCell :colspan="row.getAllCells().length">
|
||||
{{ JSON.stringify(row.original) }}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</template>
|
||||
</template>
|
||||
<template v-else>
|
||||
<TableRow>
|
||||
<TableCell :colSpan="columns.length" class="h-24 text-center">
|
||||
No results.
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</template>
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
|
||||
### Add the expand action to the `DataTableDropDown.vue` component
|
||||
|
||||
```vue:line-numbers {12-14,34-36}
|
||||
<script setup lang="ts">
|
||||
import { MoreHorizontal } from 'lucide-vue-next'
|
||||
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger } from '@/components/ui/dropdown-menu'
|
||||
import { Button } from '@/components/ui/button'
|
||||
|
||||
defineProps<{
|
||||
payment: {
|
||||
id: string
|
||||
}
|
||||
}>()
|
||||
|
||||
defineEmits<{
|
||||
(e: 'expand'): void
|
||||
}>()
|
||||
|
||||
function copy(id: string) {
|
||||
navigator.clipboard.writeText(id)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger as-child>
|
||||
<Button variant="ghost" class="w-8 h-8 p-0">
|
||||
<span class="sr-only">Open menu</span>
|
||||
<MoreHorizontal class="w-4 h-4" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuLabel>Actions</DropdownMenuLabel>
|
||||
<DropdownMenuItem @click="copy(payment.id)">
|
||||
Copy payment ID
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem @click="$emit('expand')">
|
||||
Expand
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem>View customer</DropdownMenuItem>
|
||||
<DropdownMenuItem>View payment details</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</template>
|
||||
```
|
||||
|
||||
### Make rows expandable
|
||||
|
||||
Now we can update the action cell to add the expand control.
|
||||
|
||||
```vue:line-numbers {11}
|
||||
<script setup lang="ts">
|
||||
export const columns: ColumnDef<Payment>[] = [
|
||||
{
|
||||
id: 'actions',
|
||||
enableHiding: false,
|
||||
cell: ({ row }) => {
|
||||
const payment = row.original
|
||||
|
||||
return h('div', { class: 'relative' }, h(DropdownAction, {
|
||||
payment,
|
||||
onExpand: row.toggleExpanded,
|
||||
}))
|
||||
},
|
||||
},
|
||||
]
|
||||
</script>
|
||||
|
||||
```
|
||||
|
||||
</Steps>
|
||||
|
||||
## Reusable Components
|
||||
|
||||
Here are some components you can use to build your data tables. This is from the [Tasks](/examples/tasks) demo.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<script setup lang="ts">
|
||||
import type {
|
||||
ColumnFiltersState,
|
||||
ExpandedState,
|
||||
SortingState,
|
||||
VisibilityState,
|
||||
} from '@tanstack/vue-table'
|
||||
|
|
@ -8,10 +9,10 @@ import {
|
|||
FlexRender,
|
||||
createColumnHelper,
|
||||
getCoreRowModel,
|
||||
getExpandedRowModel,
|
||||
getFilteredRowModel,
|
||||
getPaginationRowModel,
|
||||
getSortedRowModel,
|
||||
|
||||
useVueTable,
|
||||
} from '@tanstack/vue-table'
|
||||
import { ArrowUpDown, ChevronDown } from 'lucide-vue-next'
|
||||
|
|
@ -133,6 +134,7 @@ const columns = [
|
|||
|
||||
return h('div', { class: 'relative' }, h(DropdownAction, {
|
||||
payment,
|
||||
onExpand: row.toggleExpanded,
|
||||
}))
|
||||
},
|
||||
}),
|
||||
|
|
@ -142,6 +144,7 @@ const sorting = ref<SortingState>([])
|
|||
const columnFilters = ref<ColumnFiltersState>([])
|
||||
const columnVisibility = ref<VisibilityState>({})
|
||||
const rowSelection = ref({})
|
||||
const expanded = ref<ExpandedState>({})
|
||||
|
||||
const table = useVueTable({
|
||||
data,
|
||||
|
|
@ -150,15 +153,18 @@ const table = useVueTable({
|
|||
getPaginationRowModel: getPaginationRowModel(),
|
||||
getSortedRowModel: getSortedRowModel(),
|
||||
getFilteredRowModel: getFilteredRowModel(),
|
||||
getExpandedRowModel: getExpandedRowModel(),
|
||||
onSortingChange: updaterOrValue => valueUpdater(updaterOrValue, sorting),
|
||||
onColumnFiltersChange: updaterOrValue => valueUpdater(updaterOrValue, columnFilters),
|
||||
onColumnVisibilityChange: updaterOrValue => valueUpdater(updaterOrValue, columnVisibility),
|
||||
onRowSelectionChange: updaterOrValue => valueUpdater(updaterOrValue, rowSelection),
|
||||
onExpandedChange: updaterOrValue => valueUpdater(updaterOrValue, expanded),
|
||||
state: {
|
||||
get sorting() { return sorting.value },
|
||||
get columnFilters() { return columnFilters.value },
|
||||
get columnVisibility() { return columnVisibility.value },
|
||||
get rowSelection() { return rowSelection.value },
|
||||
get expanded() { return expanded.value },
|
||||
columnPinning: {
|
||||
left: ['status'],
|
||||
},
|
||||
|
|
@ -213,21 +219,24 @@ const table = useVueTable({
|
|||
</TableHeader>
|
||||
<TableBody>
|
||||
<template v-if="table.getRowModel().rows?.length">
|
||||
<TableRow
|
||||
v-for="row in table.getRowModel().rows"
|
||||
:key="row.id"
|
||||
:data-state="row.getIsSelected() && 'selected'"
|
||||
>
|
||||
<TableCell
|
||||
v-for="cell in row.getVisibleCells()" :key="cell.id" :data-pinned="cell.column.getIsPinned()"
|
||||
:class="cn(
|
||||
{ 'sticky bg-background/95': cell.column.getIsPinned() },
|
||||
cell.column.getIsPinned() === 'left' ? 'left-0' : 'right-0',
|
||||
)"
|
||||
>
|
||||
<FlexRender :render="cell.column.columnDef.cell" :props="cell.getContext()" />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<template v-for="row in table.getRowModel().rows" :key="row.id">
|
||||
<TableRow :data-state="row.getIsSelected() && 'selected'">
|
||||
<TableCell
|
||||
v-for="cell in row.getVisibleCells()" :key="cell.id" :data-pinned="cell.column.getIsPinned()"
|
||||
:class="cn(
|
||||
{ 'sticky bg-background/95': cell.column.getIsPinned() },
|
||||
cell.column.getIsPinned() === 'left' ? 'left-0' : 'right-0',
|
||||
)"
|
||||
>
|
||||
<FlexRender :render="cell.column.columnDef.cell" :props="cell.getContext()" />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow v-if="row.getIsExpanded()">
|
||||
<TableCell :colspan="row.getAllCells().length">
|
||||
{{ row.original }}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<TableRow v-else>
|
||||
|
|
|
|||
|
|
@ -2,12 +2,14 @@
|
|||
import type {
|
||||
ColumnDef,
|
||||
ColumnFiltersState,
|
||||
ExpandedState,
|
||||
SortingState,
|
||||
VisibilityState,
|
||||
} from '@tanstack/vue-table'
|
||||
import {
|
||||
FlexRender,
|
||||
getCoreRowModel,
|
||||
getExpandedRowModel,
|
||||
getFilteredRowModel,
|
||||
getPaginationRowModel,
|
||||
getSortedRowModel,
|
||||
|
|
@ -130,6 +132,7 @@ const columns: ColumnDef<Payment>[] = [
|
|||
|
||||
return h('div', { class: 'relative' }, h(DropdownAction, {
|
||||
payment,
|
||||
onExpand: row.toggleExpanded,
|
||||
}))
|
||||
},
|
||||
},
|
||||
|
|
@ -139,6 +142,7 @@ const sorting = ref<SortingState>([])
|
|||
const columnFilters = ref<ColumnFiltersState>([])
|
||||
const columnVisibility = ref<VisibilityState>({})
|
||||
const rowSelection = ref({})
|
||||
const expanded = ref<ExpandedState>({})
|
||||
|
||||
const table = useVueTable({
|
||||
data,
|
||||
|
|
@ -147,15 +151,18 @@ const table = useVueTable({
|
|||
getPaginationRowModel: getPaginationRowModel(),
|
||||
getSortedRowModel: getSortedRowModel(),
|
||||
getFilteredRowModel: getFilteredRowModel(),
|
||||
getExpandedRowModel: getExpandedRowModel(),
|
||||
onSortingChange: updaterOrValue => valueUpdater(updaterOrValue, sorting),
|
||||
onColumnFiltersChange: updaterOrValue => valueUpdater(updaterOrValue, columnFilters),
|
||||
onColumnVisibilityChange: updaterOrValue => valueUpdater(updaterOrValue, columnVisibility),
|
||||
onRowSelectionChange: updaterOrValue => valueUpdater(updaterOrValue, rowSelection),
|
||||
onExpandedChange: updaterOrValue => valueUpdater(updaterOrValue, expanded),
|
||||
state: {
|
||||
get sorting() { return sorting.value },
|
||||
get columnFilters() { return columnFilters.value },
|
||||
get columnVisibility() { return columnVisibility.value },
|
||||
get rowSelection() { return rowSelection.value },
|
||||
get expanded() { return expanded.value },
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
|
@ -201,15 +208,18 @@ const table = useVueTable({
|
|||
</TableHeader>
|
||||
<TableBody>
|
||||
<template v-if="table.getRowModel().rows?.length">
|
||||
<TableRow
|
||||
v-for="row in table.getRowModel().rows"
|
||||
:key="row.id"
|
||||
:data-state="row.getIsSelected() && 'selected'"
|
||||
>
|
||||
<TableCell v-for="cell in row.getVisibleCells()" :key="cell.id">
|
||||
<FlexRender :render="cell.column.columnDef.cell" :props="cell.getContext()" />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<template v-for="row in table.getRowModel().rows" :key="row.id">
|
||||
<TableRow :data-state="row.getIsSelected() && 'selected'">
|
||||
<TableCell v-for="cell in row.getVisibleCells()" :key="cell.id">
|
||||
<FlexRender :render="cell.column.columnDef.cell" :props="cell.getContext()" />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow v-if="row.getIsExpanded()">
|
||||
<TableCell :colspan="row.getAllCells().length">
|
||||
{{ JSON.stringify(row.original) }}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<TableRow v-else>
|
||||
|
|
|
|||
|
|
@ -9,6 +9,10 @@ defineProps<{
|
|||
}
|
||||
}>()
|
||||
|
||||
defineEmits<{
|
||||
(e: 'expand'): void
|
||||
}>()
|
||||
|
||||
function copy(id: string) {
|
||||
navigator.clipboard.writeText(id)
|
||||
}
|
||||
|
|
@ -27,6 +31,9 @@ function copy(id: string) {
|
|||
<DropdownMenuItem @click="copy(payment.id)">
|
||||
Copy payment ID
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem @click="$emit('expand')">
|
||||
Expand
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem>View customer</DropdownMenuItem>
|
||||
<DropdownMenuItem>View payment details</DropdownMenuItem>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<script setup lang="ts">
|
||||
import type {
|
||||
ColumnFiltersState,
|
||||
ExpandedState,
|
||||
SortingState,
|
||||
VisibilityState,
|
||||
} from '@tanstack/vue-table'
|
||||
|
|
@ -8,10 +9,10 @@ import {
|
|||
FlexRender,
|
||||
createColumnHelper,
|
||||
getCoreRowModel,
|
||||
getExpandedRowModel,
|
||||
getFilteredRowModel,
|
||||
getPaginationRowModel,
|
||||
getSortedRowModel,
|
||||
|
||||
useVueTable,
|
||||
} from '@tanstack/vue-table'
|
||||
import { CaretSortIcon, ChevronDownIcon } from '@radix-icons/vue'
|
||||
|
|
@ -133,6 +134,7 @@ const columns = [
|
|||
|
||||
return h('div', { class: 'relative' }, h(DropdownAction, {
|
||||
payment,
|
||||
onExpand: row.toggleExpanded,
|
||||
}))
|
||||
},
|
||||
}),
|
||||
|
|
@ -142,6 +144,7 @@ const sorting = ref<SortingState>([])
|
|||
const columnFilters = ref<ColumnFiltersState>([])
|
||||
const columnVisibility = ref<VisibilityState>({})
|
||||
const rowSelection = ref({})
|
||||
const expanded = ref<ExpandedState>({})
|
||||
|
||||
const table = useVueTable({
|
||||
data,
|
||||
|
|
@ -150,15 +153,18 @@ const table = useVueTable({
|
|||
getPaginationRowModel: getPaginationRowModel(),
|
||||
getSortedRowModel: getSortedRowModel(),
|
||||
getFilteredRowModel: getFilteredRowModel(),
|
||||
getExpandedRowModel: getExpandedRowModel(),
|
||||
onSortingChange: updaterOrValue => valueUpdater(updaterOrValue, sorting),
|
||||
onColumnFiltersChange: updaterOrValue => valueUpdater(updaterOrValue, columnFilters),
|
||||
onColumnVisibilityChange: updaterOrValue => valueUpdater(updaterOrValue, columnVisibility),
|
||||
onRowSelectionChange: updaterOrValue => valueUpdater(updaterOrValue, rowSelection),
|
||||
onExpandedChange: updaterOrValue => valueUpdater(updaterOrValue, expanded),
|
||||
state: {
|
||||
get sorting() { return sorting.value },
|
||||
get columnFilters() { return columnFilters.value },
|
||||
get columnVisibility() { return columnVisibility.value },
|
||||
get rowSelection() { return rowSelection.value },
|
||||
get expanded() { return expanded.value },
|
||||
columnPinning: {
|
||||
left: ['status'],
|
||||
},
|
||||
|
|
@ -213,21 +219,24 @@ const table = useVueTable({
|
|||
</TableHeader>
|
||||
<TableBody>
|
||||
<template v-if="table.getRowModel().rows?.length">
|
||||
<TableRow
|
||||
v-for="row in table.getRowModel().rows"
|
||||
:key="row.id"
|
||||
:data-state="row.getIsSelected() && 'selected'"
|
||||
>
|
||||
<TableCell
|
||||
v-for="cell in row.getVisibleCells()" :key="cell.id" :data-pinned="cell.column.getIsPinned()"
|
||||
:class="cn(
|
||||
{ 'sticky bg-background/95': cell.column.getIsPinned() },
|
||||
cell.column.getIsPinned() === 'left' ? 'left-0' : 'right-0',
|
||||
)"
|
||||
>
|
||||
<FlexRender :render="cell.column.columnDef.cell" :props="cell.getContext()" />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<template v-for="row in table.getRowModel().rows" :key="row.id">
|
||||
<TableRow :data-state="row.getIsSelected() && 'selected'">
|
||||
<TableCell
|
||||
v-for="cell in row.getVisibleCells()" :key="cell.id" :data-pinned="cell.column.getIsPinned()"
|
||||
:class="cn(
|
||||
{ 'sticky bg-background/95': cell.column.getIsPinned() },
|
||||
cell.column.getIsPinned() === 'left' ? 'left-0' : 'right-0',
|
||||
)"
|
||||
>
|
||||
<FlexRender :render="cell.column.columnDef.cell" :props="cell.getContext()" />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow v-if="row.getIsExpanded()">
|
||||
<TableCell :colspan="row.getAllCells().length">
|
||||
{{ JSON.stringify(row.original) }}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<TableRow v-else>
|
||||
|
|
|
|||
|
|
@ -2,12 +2,14 @@
|
|||
import type {
|
||||
ColumnDef,
|
||||
ColumnFiltersState,
|
||||
ExpandedState,
|
||||
SortingState,
|
||||
VisibilityState,
|
||||
} from '@tanstack/vue-table'
|
||||
import {
|
||||
FlexRender,
|
||||
getCoreRowModel,
|
||||
getExpandedRowModel,
|
||||
getFilteredRowModel,
|
||||
getPaginationRowModel,
|
||||
getSortedRowModel,
|
||||
|
|
@ -130,6 +132,7 @@ const columns: ColumnDef<Payment>[] = [
|
|||
|
||||
return h(DropdownAction, {
|
||||
payment,
|
||||
onExpand: row.toggleExpanded,
|
||||
})
|
||||
},
|
||||
},
|
||||
|
|
@ -139,6 +142,7 @@ const sorting = ref<SortingState>([])
|
|||
const columnFilters = ref<ColumnFiltersState>([])
|
||||
const columnVisibility = ref<VisibilityState>({})
|
||||
const rowSelection = ref({})
|
||||
const expanded = ref<ExpandedState>({})
|
||||
|
||||
const table = useVueTable({
|
||||
data,
|
||||
|
|
@ -147,15 +151,18 @@ const table = useVueTable({
|
|||
getPaginationRowModel: getPaginationRowModel(),
|
||||
getSortedRowModel: getSortedRowModel(),
|
||||
getFilteredRowModel: getFilteredRowModel(),
|
||||
getExpandedRowModel: getExpandedRowModel(),
|
||||
onSortingChange: updaterOrValue => valueUpdater(updaterOrValue, sorting),
|
||||
onColumnFiltersChange: updaterOrValue => valueUpdater(updaterOrValue, columnFilters),
|
||||
onColumnVisibilityChange: updaterOrValue => valueUpdater(updaterOrValue, columnVisibility),
|
||||
onRowSelectionChange: updaterOrValue => valueUpdater(updaterOrValue, rowSelection),
|
||||
onExpandedChange: updaterOrValue => valueUpdater(updaterOrValue, expanded),
|
||||
state: {
|
||||
get sorting() { return sorting.value },
|
||||
get columnFilters() { return columnFilters.value },
|
||||
get columnVisibility() { return columnVisibility.value },
|
||||
get rowSelection() { return rowSelection.value },
|
||||
get expanded() { return expanded.value },
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
|
@ -201,15 +208,18 @@ const table = useVueTable({
|
|||
</TableHeader>
|
||||
<TableBody>
|
||||
<template v-if="table.getRowModel().rows?.length">
|
||||
<TableRow
|
||||
v-for="row in table.getRowModel().rows"
|
||||
:key="row.id"
|
||||
:data-state="row.getIsSelected() && 'selected'"
|
||||
>
|
||||
<TableCell v-for="cell in row.getVisibleCells()" :key="cell.id">
|
||||
<FlexRender :render="cell.column.columnDef.cell" :props="cell.getContext()" />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<template v-for="row in table.getRowModel().rows" :key="row.id">
|
||||
<TableRow :data-state="row.getIsSelected() && 'selected'">
|
||||
<TableCell v-for="cell in row.getVisibleCells()" :key="cell.id">
|
||||
<FlexRender :render="cell.column.columnDef.cell" :props="cell.getContext()" />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow v-if="row.getIsExpanded()">
|
||||
<TableCell :colspan="row.getAllCells().length">
|
||||
{{ JSON.stringify(row.original) }}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<TableRow v-else>
|
||||
|
|
|
|||
|
|
@ -9,6 +9,10 @@ defineProps<{
|
|||
}
|
||||
}>()
|
||||
|
||||
defineEmits<{
|
||||
(e: 'expand'): void
|
||||
}>()
|
||||
|
||||
function copy(id: string) {
|
||||
navigator.clipboard.writeText(id)
|
||||
}
|
||||
|
|
@ -27,6 +31,9 @@ function copy(id: string) {
|
|||
<DropdownMenuItem @click="copy(payment.id)">
|
||||
Copy payment ID
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem @click="$emit('expand')">
|
||||
Expand
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem>View customer</DropdownMenuItem>
|
||||
<DropdownMenuItem>View payment details</DropdownMenuItem>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user