chore(Table): handle default sort and default column direction

This commit is contained in:
Benjamin Canac
2023-05-30 17:59:30 +02:00
parent a2638c6057
commit 40b6884424
3 changed files with 31 additions and 16 deletions

View File

@@ -13,7 +13,8 @@ const columns = [{
}, {
key: 'email',
label: 'Email',
sortable: true
sortable: true,
direction: 'desc'
}, {
key: 'role',
label: 'Role'
@@ -59,5 +60,5 @@ const people = [{
</script>
<template>
<UTable :columns="columns" :rows="people" />
<UTable :columns="columns" :rows="people" :sort="{ column: 'title' }" />
</template>

View File

@@ -70,6 +70,7 @@ Use the `columns` prop to configure which columns to display. It's an array of o
- `label` - The label to display in the table header. Can be changed through the `column-attribute` prop.
- `key` - The field to display from the row data.
- `sortable` - Whether the column is sortable. Defaults to `false`.
- `direction` - The sort direction to use on first click. Defaults to `asc`.
::component-example
---
@@ -181,7 +182,8 @@ const columns = [{
}, {
key: 'email',
label: 'Email',
sortable: true
sortable: true,
direction: 'desc'
}, {
key: 'role',
label: 'Role'
@@ -191,11 +193,18 @@ const people = [...]
</script>
<template>
<UTable :columns="columns" :rows="people" />
<UTable :columns="columns" :rows="people" :sort="{ column: 'title' }" />
</template>
```
::
You can specify the default direction of each column through the `direction` property. It can be either `asc` or `desc` and defaults to `asc`.
You can specify a default sort for the table through the `sort` prop. It's an object with the following properties:
- `column` - The column to sort by.
- `direction` - The sort direction. Can be either `asc` or `desc` and defaults to `asc`.
Use the `sort-button` prop to customize the sort button in the header. You can pass all the props of the [Button](/elements/button) component to customize it through this prop or globally through `ui.table.default.sortButton`. Its icon defaults to `i-heroicons-arrows-up-down-20-solid`.
::component-card
@@ -358,7 +367,7 @@ The `sort` property is an object with the following properties:
- `field` - The field to sort by.
- `direction` - The direction to sort by. Can be `asc` or `desc`.
The `on-sort` property is a function that you can call to sort the table. It accepts a string with the field to sort by and an optional string with the direction to sort by. If the direction is not provided, it will toggle between `asc` and `desc`.
The `on-sort` property is a function that you can call to sort the table and accepts the column as parameter.
::alert{icon="i-heroicons-light-bulb"}
Even though you can customize the sort button as mentioned in the [Sortable](#sortable) section, you can use this slot to completely override its behavior, with a custom dropdown for example.

View File

@@ -12,9 +12,9 @@
<UButton
v-if="column.sortable"
v-bind="sortButton"
:icon="(!sort.field || sort.field !== column.key) ? sortButton.icon : sort.direction === 'asc' ? sortAscIcon : sortDescIcon"
:icon="(!sort.column || sort.column !== column.key) ? sortButton.icon : sort.direction === 'asc' ? sortAscIcon : sortDescIcon"
:label="column[columnAttribute]"
@click="onSort(column.key)"
@click="onSort(column)"
/>
<span v-else>{{ column[columnAttribute] }}</span>
</slot>
@@ -77,6 +77,10 @@ export default defineComponent({
type: String,
default: 'label'
},
sort: {
type: Object,
default: () => ({})
},
sortButton: {
type: Object as PropType<Partial<Button>>,
default: () => appConfig.ui.table.default.sortButton
@@ -101,18 +105,18 @@ export default defineComponent({
const ui = computed<Partial<typeof appConfig.ui.table>>(() => defu({}, props.ui, appConfig.ui.table))
const sort = ref({ field: null, direction: null })
const columns = computed(() => props.columns ?? Object.keys(props.rows[0] ?? {}).map((key) => ({ key, label: capitalize(key), sortable: false })))
const sort = ref(defu({}, props.sort, { column: null, direction: 'asc' }))
const rows = computed(() => {
if (!sort.value?.field) {
if (!sort.value?.column) {
return props.rows
}
const { field, direction } = sort.value
const { column, direction } = sort.value
return orderBy(props.rows, field, direction)
return orderBy(props.rows, column, direction)
})
const selected = computed({
@@ -142,17 +146,18 @@ export default defineComponent({
return selected.value.some((item) => compare(toRaw(item), toRaw(row)))
}
function onSort (field: string, direction?: 'asc' | 'desc') {
if (sort.value.field === field) {
sort.value.direction = direction || sort.value.direction === 'asc' ? 'desc' : 'asc'
function onSort (column) {
if (sort.value.column === column.key) {
sort.value.direction = sort.value.direction === 'asc' ? 'desc' : 'asc'
} else {
sort.value = { field, direction: direction || 'asc' }
sort.value = { column: column.key, direction: column.direction || 'asc' }
}
}
return {
// eslint-disable-next-line vue/no-dupe-keys
ui,
// eslint-disable-next-line vue/no-dupe-keys
sort,
// eslint-disable-next-line vue/no-dupe-keys
columns,