Skip to content

Commit

Permalink
feat(Table): add v-model:sort prop (#803)
Browse files Browse the repository at this point in the history
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
  • Loading branch information
DarkGhostHunter and benjamincanac committed Oct 14, 2023
1 parent 8bfd359 commit 9f4d88e
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 4 deletions.
69 changes: 69 additions & 0 deletions docs/components/content/examples/TableExampleReactiveSorting.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<script setup>
const sort = ref({
column: 'name',
direction: 'desc'
})
const columns = [{
key: 'id',
label: 'ID'
}, {
key: 'name',
label: 'Name',
sortable: true
}, {
key: 'title',
label: 'Title',
sortable: true
}, {
key: 'email',
label: 'Email'
}, {
key: 'role',
label: 'Role',
sortable: true,
direction: 'desc'
}]
const people = [{
id: 1,
name: 'Lindsay Walton',
title: 'Front-end Developer',
email: 'lindsay.walton@example.com',
role: 'Member'
}, {
id: 2,
name: 'Courtney Henry',
title: 'Designer',
email: 'courtney.henry@example.com',
role: 'Admin'
}, {
id: 3,
name: 'Tom Cook',
title: 'Director of Product',
email: 'tom.cook@example.com',
role: 'Member'
}, {
id: 4,
name: 'Whitney Francis',
title: 'Copywriter',
email: 'whitney.francis@example.com',
role: 'Admin'
}, {
id: 5,
name: 'Leonard Krasner',
title: 'Senior Designer',
email: 'leonard.krasner@example.com',
role: 'Owner'
}, {
id: 6,
name: 'Floyd Miles',
title: 'Principal Designer',
email: 'floyd.miles@example.com',
role: 'Member'
}]
</script>

<template>
<UTable v-model:sort="sort" :columns="columns" :rows="people" />
</template>
40 changes: 39 additions & 1 deletion docs/content/4.data/1.table.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ componentProps:
---
::

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 may specify the default direction of each column through the `direction` property. It can be either `asc` or `desc`, but it will default to `asc`.

You can specify a default sort for the table through the `sort` prop. It's an object with the following properties:

Expand Down Expand Up @@ -156,6 +156,44 @@ Use the `sort-desc-icon` prop to set a different icon or change it globally in `
You can also customize the entire header cell, read more in the [Slots](#slots) section.
::

#### Reactive sorting :u-badge{label="New" class="align-middle ml-2 !rounded-full" variant="subtle"}

Sometimes you will want to fetch new data depending on the sorted column and direction. You can use the `v-model:sort` to automatically update the `ref` reactive element every time the sorting changes on the Table. You may also use `@update:sort` to call your own function with the sorting data.

For example, we can take advantage of `useLazyRefresh` computed URL to automatically fetch the data depending on the sorting column and direction every time the `sort` reactive element changes.

```vue
<script setup>
// Ensure it uses `ref` instead of `reactive`.
const sort = ref({
column: 'name',
direction: 'desc'
})
const columns = [...]
const { data, pending } = useLazyFetch(() => {
return `/api/users?orderBy=${sort.value.column}&order=${sort.value.direction}`
})
</script>
<template>
<UTable v-model:sort="sort" :loading="pending" :columns="columns" :rows="data" />
</template>
```

The initial value of `sort` will be respected as the initial sort column and direction, as well as each column default sorting direction.

::component-example{class="grid"}
---
padding: false
overflowClass: 'overflow-x-auto'
component: 'table-example-reactive-sorting'
componentProps:
class: 'flex-1'
---
::

### Selectable

Use a `v-model` to make the table selectable. The `v-model` will be an array of the selected rows.
Expand Down
8 changes: 6 additions & 2 deletions src/runtime/components/data/Table.vue
Original file line number Diff line number Diff line change
Expand Up @@ -152,14 +152,16 @@ export default defineComponent({
default: undefined
}
},
emits: ['update:modelValue'],
emits: ['update:modelValue', 'update:sort'],
setup (props, { emit, attrs: $attrs }) {
const { ui, attrs } = useUI('table', toRef(props, 'ui'), config, toRef(props, 'class'))
const columns = computed(() => props.columns ?? Object.keys(omit(props.rows[0] ?? {}, ['click'])).map((key) => ({ key, label: upperFirst(key), sortable: false })))
const sort = ref(defu({}, props.sort, { column: null, direction: 'asc' }))
const defaultSort = { column: sort.value.column, direction: null }
const rows = computed(() => {
if (!sort.value?.column) {
return props.rows
Expand Down Expand Up @@ -225,13 +227,15 @@ export default defineComponent({
const direction = !column.direction || column.direction === 'asc' ? 'desc' : 'asc'
if (sort.value.direction === direction) {
sort.value = defu({}, props.sort, { column: null, direction: 'asc' })
sort.value = defu({}, defaultSort, { column: null, direction: 'asc' })
} else {
sort.value.direction = sort.value.direction === 'asc' ? 'desc' : 'asc'
}
} else {
sort.value = { column: column.key, direction: column.direction || 'asc' }
}
emit('update:sort', sort.value)
}
function onSelect (row) {
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/components/forms/Input.vue
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export default defineComponent({
},
autofocusDelay: {
type: Number,
default: 100,
default: 100
},
icon: {
type: String,
Expand Down

1 comment on commit 9f4d88e

@vercel
Copy link

@vercel vercel bot commented on 9f4d88e Oct 14, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

ui – ./

ui-nuxt-js.vercel.app
ui-git-dev-nuxt-js.vercel.app
ui.nuxt.com

Please sign in to comment.