Vuetify is a popular UI framework for Vue apps.
In this article, we’ll look at how to work with the Vuetify framework.
External Sorting
We can control sorting externally with various props.
For instance, we can write:
<template>
<div>
<v-data-table
:headers="headers"
:items="desserts"
:sort-by.sync="sortBy"
:sort-desc.sync="sortDesc"
class="elevation-1"
></v-data-table>
<div class="text-center pt-2">
<v-btn color="primary" class="mr-2" @click="toggleOrder">Toggle sort order</v-btn>
<v-btn color="primary" @click="nextSort">Sort next column</v-btn>
</div>
</div>
</template>
<script>
export default {
name: "HelloWorld",
data: () => ({
sortBy: "fat",
sortDesc: false,
headers: [
{
text: "Dessert (100g serving)",
align: "start",
value: "name",
},
{ text: "Calories", value: "calories" },
{ text: "Fat (g)", value: "fat" },
],
desserts: [
{
name: "Frozen Yogurt",
calories: 159,
fat: 6.0,
},
{
name: "Ice cream sandwich",
calories: 237,
fat: 9.0,
},
{
name: "Eclair",
calories: 262,
fat: 16.0,
},
],
}),
methods: {
toggleOrder() {
this.sortDesc = !this.sortDesc;
},
nextSort() {
let index = this.headers.findIndex((h) => h.value === this.sortBy);
index = (index + 1) % this.headers.length;
this.sortBy = this.headers[index].value;
},
},
};
</script>
We change the sortBy
and sortDesc
prop values to let us change the column to sort by and whether we sort ascending or descending respectively.
The sync
modifier is required for updating the table properly when the buttons are clicked to change the prop values.
Paginate and Sort Server-Side
We can do the pagination and sorting on the server-side.
For example, we can write:
<template>
<div>
<v-data-table
:headers="headers"
:items="desserts"
:options.sync="options"
:server-items-length="totalDesserts"
:loading="loading"
class="elevation-1"
></v-data-table>
</div>
</template>
<script>
export default {
name: "HelloWorld",
data() {
return {
totalDesserts: 0,
desserts: [],
loading: true,
options: {},
headers: [
{
text: "Dessert (100g serving)",
align: "start",
sortable: false,
value: "name",
},
{ text: "Calories", value: "calories" },
{ text: "Fat (g)", value: "fat" },
],
};
},
watch: {
options: {
async handler() {
const { items, total } = await this.getDataFromApi();
this.desserts = items;
this.totalDesserts = total;
},
deep: true,
},
},
async mounted() {
const { items, total } = await this.getDataFromApi();
this.desserts = items;
this.totalDesserts = total;
},
methods: {
getDataFromApi() {
this.loading = true;
return new Promise((resolve, reject) => {
const { sortBy, sortDesc, page, itemsPerPage } = this.options;
let items = this.getDesserts();
const total = items.length;
if (sortBy.length === 1 && sortDesc.length === 1) {
items = items.sort((a, b) => {
const sortA = a[sortBy[0]];
const sortB = b[sortBy[0]];
if (sortDesc[0]) {
if (sortA < sortB) return 1;
if (sortA > sortB) return -1;
return 0;
} else {
if (sortA < sortB) return -1;
if (sortA > sortB) return 1;
return 0;
}
});
}
if (itemsPerPage > 0) {
items = items.slice((page - 1) * itemsPerPage, page * itemsPerPage);
}
setTimeout(() => {
this.loading = false;
resolve({
items,
total,
});
}, 1000);
});
},
getDesserts() {
return [
{
name: "Frozen Yogurt",
calories: 159,
fat: 6.0,
},
{
name: "Ice cream sandwich",
calories: 237,
fat: 9.0,
},
{
name: "Eclair",
calories: 262,
fat: 16.0,
},
];
},
},
};
</script>
The getDataFromApi
method returns a promise that resolves to the data that we want to populate in the table.
The sorting is done with the sort
method in the promise.
In the mounted
hook, we get the data and set it.
this.desserts
has the items.
totalDesserts
is a number with the total number of desserts.
We set totalDessert
as the value of server-items-length
.
And items
has the desserts
array as its value.
Conclusion
We can sort and paginate data from the client or server-side with Vuetify.