Sortable
A table which can be sorted by clicking the column headers. The component requires an array of objects each bound to a rows
and columns
property.
Properties of column objects
Property | Required | Type | Description |
---|---|---|---|
label | yes | String | Label in the table header; required, but can be an empty string |
prop | yes | String | The property of a row object displayed in this column |
sortable | Boolean | If missing or false , won't allow user interaction | |
sortAscFunction | Function | Replaces the default sort function for ascending sorts | |
sortDescFunction | Function | Replaces the default sort function for descending sorts | |
cssClass | String | Defines extra classes applied to the th elements |
Row objects should provide a property which can be used as key
attribute in the list rendering.
As default a key
property is assumed but can be declared otherwise with the key-property
attribute of the component.
Default Component
js
const cols = [
{ label: 'Name', prop: 'name', sortable: true },
{ label: 'Role', prop: 'role', sortable: true },
{ label: 'Born in', prop: 'yob', sortable: true }
]
const rows = ref([
{ key: 1, name: 'Linda', role: 'Sarah', yob: 1956 },
{ key: 2, name: 'Robert', role: 'T1000', yob: 1958 },
{ key: 3, name: 'Arnold', role: 'T800', yob: 1947 },
{ key: 4, name: 'Edward', role: 'John', yob: 1977 },
{ key: 5, name: 'Michael', role: 'Kyle', yob: 1956 },
{ key: 6, name: 'Joe', role: 'Miles', yob: 1947 },
{ key: 7, name: 'Kristanna', role: 'T-X', yob: 1979 },
{ key: 8, name: 'Gabriel', role: 'REV-9', yob: 1982 },
{ key: 9, name: 'Mackenzie', role: 'Grace', yob: 1987 },
])
html
<sortable :rows="rows" :columns="cols" />
Result
Name | Role | Born in |
---|---|---|
Linda | Sarah | 1956 |
Robert | T1000 | 1958 |
Arnold | T800 | 1947 |
Edward | John | 1977 |
Michael | Kyle | 1956 |
Joe | Miles | 1947 |
Kristanna | T-X | 1979 |
Gabriel | REV-9 | 1982 |
Mackenzie | Grace | 1987 |
Component using offset and count
Useful in combination with a pagination component. The Role column has sorting disabled.
js
const offset = ref(0)
const count = ref(4)
const cols = [
{ label: 'Name', prop: 'name', sortable: true },
{ label: 'Role', prop: 'role' },
{ label: 'Born in', prop: 'yob', sortable: true }
]
const rows = ref([
{ key: 1, name: "Robert", yob: 1958, role: "T1000" },
{ key: 2, name: "Harrison", yob: 1942, role: "Indiana Jones" },
{ key: 3, name: "Morgan", yob: 1937, role: "Red" },
{ key: 4, name: "Sigourney", yob: 1949, role: "Ripley" },
{ key: 5, name: "Tom", yob: 1962, role: "Forrest Gump" },
{ key: 6, name: "Jodie", yob: 1962, role: "Clarice Starling" },
{ key: 7, name: "Bruce", yob: 1955, role: "John McClane" },
{ key: 8, name: "Julia", yob: 1967, role: "Vivian Ward" },
{ key: 9, name: "Jack", yob: 1937, role: "Jack Torrance" },
{ key: 10, name: "Uma", yob: 1970, role: "The Bride" },
{ key: 11, name: "Johnny", yob: 1963, role: "Jack Sparrow" },
{ key: 12, name: "Leonardo", yob: 1974, role: "Jack Dawson" },
{ key: 13, name: "Angelina", yob: 1975, role: "Lara Croft" },
{ key: 14, name: "Keanu", yob: 1964, role: "Neo" },
{ key: 15, name: "Anthony", yob: 1937, role: "Hannibal Lecter" },
{ key: 16, name: "Charlize", yob: 1975, role: "Imperator Furiosa" },
{ key: 17, name: "Jim", yob: 1962, role: "Ace Ventura" },
{ key: 18, name: "Meryl", yob: 1949, role: "Miranda Priestly" },
{ key: 19, name: "Daniel", yob: 1968, role: "James Bond" },
{ key: 20, name: "Ian", yob: 1939, role: "Gandalf" }
])
html
<div class="flex items-center space-x-2">
<button class="px-4 py-2 bg-vxvue text-white rounded" @click="offset = Math.max(0, offset - 1)">-</button>
<span>Offset {{ offset }}</span>
<button class="px-4 py-2 bg-vxvue text-white rounded" @click="offset = Math.min(rows.length - count, offset + 1)">+</button>
</div>
<sortable :rows="rowsAlt" :columns="colsAlt" :offset="offset" :count="count" />
Result
Offset 0
Name | Born in | Role |
---|---|---|
Robert | 1958 | T1000 |
Harrison | 1942 | Indiana Jones |
Morgan | 1937 | Red |
Sigourney | 1949 | Ripley |
Component Using Slots
Slots are exposed for both table headers and table cells.4
js
const cols = [
{ label: 'Name', prop: 'name', sortable: true },
{ label: 'Role', prop: 'role', sortable: true },
{ label: 'Born in', prop: 'yob', sortable: true }
]
const rows = ref([
{ key: 1, name: 'Linda', role: 'Sarah', yob: 1956 },
{ key: 2, name: 'Robert', role: 'T1000', yob: 1958 },
{ key: 3, name: 'Arnold', role: 'T800', yob: 1947 },
{ key: 4, name: 'Edward', role: 'John', yob: 1977 },
{ key: 5, name: 'Michael', role: 'Kyle', yob: 1956 },
{ key: 6, name: 'Joe', role: 'Miles', yob: 1947 },
{ key: 7, name: 'Kristanna', role: 'T-X', yob: 1979 },
{ key: 8, name: 'Gabriel', role: 'REV-9', yob: 1982 },
{ key: 9, name: 'Mackenzie', role: 'Grace', yob: 1987 },
])
html
<sortable :rows="rows" :columns="cols">
<template #name-header="slotProps">
<div :class="['w-32 flex items-center justify-between', slotProps.sortProp === 'name' ? 'text-white' : 'text-vxvue']">
<span>{{ slotProps.column.label }}</span>
<span v-if="slotProps.sortProp === 'name'">{{ slotProps.sortDir === 'asc' ? '+' : '-' }}</span>
</div>
</template>
<template #role-header="slotProps">
<div :class="['w-32 flex items-center justify-between', slotProps.sortProp === 'role' ? 'text-white' : 'text-vxvue']">
<span>{{ slotProps.column.label }}</span>
<span v-if="slotProps.sortProp === 'role'">{{ slotProps.sortDir === 'asc' ? '+' : '-' }}</span>
</div>
</template>
<template #yob-header="slotProps">
<div :class="['w-48 flex items-center justify-between', slotProps.sortProp === 'yob' ? 'text-white' : 'text-vxvue']">
<span>YOB</span>
<span v-if="slotProps.sortProp === 'yob'">{{ slotProps.sortDir === 'asc' ? '+' : '-' }}</span>
</div>
</template>
<template #yob="slotProps">
<em>{{ slotProps.row.name }} was born in</em> {{ slotProps.row.yob }}
</template>
</sortable>
Result
Name | Role | YOB |
---|---|---|
Linda | Sarah | Linda was born in 1956 |
Robert | T1000 | Robert was born in 1958 |
Arnold | T800 | Arnold was born in 1947 |
Edward | John | Edward was born in 1977 |
Michael | Kyle | Michael was born in 1956 |
Joe | Miles | Joe was born in 1947 |
Kristanna | T-X | Kristanna was born in 1979 |
Gabriel | REV-9 | Gabriel was born in 1982 |
Mackenzie | Grace | Mackenzie was born in 1987 |
Properties
Name | Type | Default | Description |
---|---|---|---|
columns | Object[] | required; defines the table columns; every object requires at least the label and the prop property | |
rows | Object[] | required; holds the row data | |
offset | Number | null | Starting index at which the sorted rows are displayed |
count | Number | null | Number of rows which are displayed |
sortProp | String | Determines whether a "previous" and "next" button will be provided | |
sortDirection | String | If set the allowed values are asc and desc | |
keyProperty | String | "key" | property in rows which is assigned to the :key attribute when filling the table |
Events
Name | Arguments | Description |
---|---|---|
before-sort | { prop: columnObject, dir: "asc", "desc") } | Fires when a column header is clicked, but before any rows are sorted |
after-sort | { prop: columnObject, dir: "asc", "desc" } | Fires after a the sorting of rows is complete |
Slots
Name | Scoped | Description |
---|---|---|
{columnProperty}-name | sortDir , sortProp , column | The content of the th element of a column |
{columnProperty} | row | The content of a td element in the sortable tbody |