From 40b6884424b4cab1c0865229b756df5991327b4c Mon Sep 17 00:00:00 2001 From: Benjamin Canac Date: Tue, 30 May 2023 17:59:30 +0200 Subject: [PATCH] chore(Table): handle default sort and default column direction --- .../examples/TableExampleColumnsSortable.vue | 5 ++-- docs/content/4.data/1.table.md | 15 ++++++++--- src/runtime/components/data/Table.vue | 27 +++++++++++-------- 3 files changed, 31 insertions(+), 16 deletions(-) diff --git a/docs/components/content/examples/TableExampleColumnsSortable.vue b/docs/components/content/examples/TableExampleColumnsSortable.vue index 2788de2e..533d4548 100644 --- a/docs/components/content/examples/TableExampleColumnsSortable.vue +++ b/docs/components/content/examples/TableExampleColumnsSortable.vue @@ -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 = [{ diff --git a/docs/content/4.data/1.table.md b/docs/content/4.data/1.table.md index 30129d0a..28d8b5fa 100644 --- a/docs/content/4.data/1.table.md +++ b/docs/content/4.data/1.table.md @@ -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 = [...] ``` :: +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. diff --git a/src/runtime/components/data/Table.vue b/src/runtime/components/data/Table.vue index f453451a..755e2861 100644 --- a/src/runtime/components/data/Table.vue +++ b/src/runtime/components/data/Table.vue @@ -12,9 +12,9 @@ {{ column[columnAttribute] }} @@ -77,6 +77,10 @@ export default defineComponent({ type: String, default: 'label' }, + sort: { + type: Object, + default: () => ({}) + }, sortButton: { type: Object as PropType>, default: () => appConfig.ui.table.default.sortButton @@ -101,18 +105,18 @@ export default defineComponent({ const ui = computed>(() => 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,