Skip to content

Commit

Permalink
feat(Table): add sort-mode prop
Browse files Browse the repository at this point in the history
Resolves #1149
  • Loading branch information
benjamincanac committed Jan 9, 2024
1 parent c6841d0 commit 56e0c9a
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,5 @@ const people = [{
</script>

<template>
<UTable :columns="columns" :rows="people" :sort="{ column: 'title' }" />
<UTable :columns="columns" :rows="people" />
</template>
108 changes: 71 additions & 37 deletions docs/content/4.data/1.table.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ componentProps:

You can make the columns sortable by setting the `sortable` property to `true` in the column configuration.

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`.

::component-example{class="grid"}
---
padding: false
Expand All @@ -63,17 +65,84 @@ componentProps:
---
::

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`.
#### Default sorting

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`.

::callout{icon="i-heroicons-light-bulb"}
This will set the default sort and will work even if no column is set as `sortable`.

```vue
<script setup>
const sort = ref({
column: 'name',
direction: 'desc'
})
const columns = [{
label: 'Name',
key: 'name',
sortable: true
}]
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'
}]
</script>
<template>
<UTable :sort="sort" :columns="columns" :rows="people" />
</template>
```

#### Reactive sorting

You can use a `v-model:sort` to make the sorting reactive. You may also use `@update:sort` to call your own function with the sorting data.

When fetching data from an API, we can take advantage of the [`useFetch`](https://nuxt.com/docs/api/composables/use-fetch) or [`useAsyncData`](https://nuxt.com/docs/api/composables/use-async-data) composables to fetch the data based on the sorting column and direction every time the `sort` reactive element changes.

When doing so, you might want to set the `sort-mode` prop to `manual` to disable the automatic sorting and return the rows as is. :u-badge{label="New" class="!rounded-full" variant="subtle"}

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

::callout{icon="i-heroicons-light-bulb" to="https://nuxt.com/docs/api/composables/use-fetch#params" target="_blank"}
We pass a function to `useLazyFetch` here make the url reactive but you can use the `query` / `params` options alongside `watch`.
::

#### Custom sorting

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{class="grid"}
Expand Down Expand Up @@ -152,41 +221,6 @@ 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

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 the `useLazyFetch` computed 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 } = await useLazyFetch(`/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
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
6 changes: 5 additions & 1 deletion src/runtime/components/data/Table.vue
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,10 @@ export default defineComponent({
type: Object as PropType<{ column: string, direction: 'asc' | 'desc' }>,
default: () => ({})
},
sortMode: {
type: String as PropType<'manual' | 'auto'>,
default: 'auto'
},
sortButton: {
type: Object as PropType<Button>,
default: () => config.default.sortButton as Button
Expand Down Expand Up @@ -176,7 +180,7 @@ export default defineComponent({
const savedSort = { column: sort.value.column, direction: null }
const rows = computed(() => {
if (!sort.value?.column) {
if (!sort.value?.column || props.sortMode === 'manual') {
return props.rows
}
Expand Down

1 comment on commit 56e0c9a

@vercel
Copy link

@vercel vercel bot commented on 56e0c9a Jan 9, 2024

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.com
ui-nuxt-js.vercel.app
ui-git-dev-nuxt-js.vercel.app

Please sign in to comment.