Vuetify is a popular UI framework for Vue apps.
In this article, we’ll look at how to work with the Vuetify framework.
Footer Props
We can change the v-data-table
‘s footer-props
prop to change the footer.
For example, we can write:
<template>
<v-data-table
:headers="headers"
:items="desserts"
:items-per-page="5"
item-key="name"
class="elevation-1"
:footer-props="{
showFirstLastPage: true,
firstIcon: 'mdi-arrow-collapse-left',
lastIcon: 'mdi-arrow-collapse-right',
prevIcon: 'mdi-minus',
nextIcon: 'mdi-plus'
}"
></v-data-table>
</template>
<script>
export default {
name: "HelloWorld",
data: () => ({
search: "",
headers: [
{
text: "Dessert (100g serving)",
align: "start",
sortable: false,
value: "name",
},
{ text: "Calories", value: "calories" },
{ text: "Fat (g)", value: "fat" },
],
desserts: [
{
name: "Frozen Yogurt",
calories: 200,
fat: 6.0,
},
{
name: "Ice cream sandwich",
calories: 200,
fat: 9.0,
},
{
name: "Eclair",
calories: 300,
fat: 16.0,
},
],
}),
};
</script>
We have an object with the firstIcon
, lastIcon
, prevIcon
, and nextIcon
properties to change the navigation buttons for the table.
showFirstLastPage
lets us show the buttons to go to the first and last page.
Filterable Columns
We can set some columns to be filterable with the filterable
property.
For example, we can write:
<template>
<v-card>
<v-card-title>
<v-text-field v-model="search" append-icon="search" label="Search" single-line hide-details></v-text-field>
</v-card-title>
<v-data-table :headers="headers" :items="desserts" :search="search"></v-data-table>
</v-card>
</template>
<script>
export default {
name: "HelloWorld",
data: () => ({
search: "",
headers: [
{
text: "Dessert (100g serving)",
align: "start",
filterable: false,
value: "name",
},
{ text: "Calories", value: "calories" },
{ text: "Fat (g)", value: "fat" },
],
desserts: [
{
name: "Frozen Yogurt",
calories: 200,
fat: 6.0,
},
{
name: "Ice cream sandwich",
calories: 200,
fat: 9.0,
},
{
name: "Eclair",
calories: 300,
fat: 16.0,
},
],
}),
};
</script>
to disable filtering on the first column.
We added the filterable
property into the object in the headers
array.
Slots
We can populate various slots with our content.
For example, we can write:
<template>
<div>
<v-select v-model="enabled" :items="slots" label="Slot" clearable></v-select>
<v-data-table
:headers="headers"
:items="items"
:search="search"
:hide-default-header="hideHeaders"
:show-select="showSelect"
:loading="isLoading"
hide-default-footer
item-key="name"
class="elevation-1"
>
<template v-if="isEnabled('top')" v-slot:top>
<div>This is content above the actual table</div>
</template>
<template
v-show="isEnabled('header.data-table-select')"
v-slot:header.data-table-select="{ on, props }"
>
<v-simple-checkbox color="purple" v-bind="props" v-on="on"></v-simple-checkbox>
</template>
<template v-if="isEnabled('header')" v-slot:header="{ props: { headers } }">
<thead>
<tr>
<th :colspan="headers.length">This is a header</th>
</tr>
</thead>
</template>
<template v-show="isEnabled('progress')" v-slot:progress>
<v-progress-linear color="purple" :height="10" indeterminate></v-progress-linear>
</template>
<template
v-show="isEnabled('item.data-table-select')"
v-slot:item.data-table-select="{ isSelected, select }"
>
<v-simple-checkbox color="green" :value="isSelected" @input="select($event)"></v-simple-checkbox>
</template>
<template
v-show="isEnabled('item.<name>')"
v-slot:item.name="{ item }"
>{{ item.name.toUpperCase() }}</template>
<template v-show="isEnabled('body.prepend')" v-slot:body.prepend="{ headers }">
<tr>
<td :colspan="headers.length">This is a prepended row</td>
</tr>
</template>
<template v-show="isEnabled('body')" v-slot:body="{ items }">
<tbody>
<tr v-for="item in items" :key="item.name">
<td>{{ item.name }}</td>
</tr>
</tbody>
</template>
<template v-show="isEnabled('no-data')" v-slot:no-data>NO DATA HERE!</template>
<template v-show="isEnabled('no-results')" v-slot:no-results>NO RESULTS HERE!</template>
<template v-show="isEnabled('body.append')" v-slot:body.append="{ headers }">
<tr>
<td :colspan="headers.length">This is an appended row</td>
</tr>
</template>
<template v-show="isEnabled('footer')" v-slot:footer>
<div>This is a footer</div>
</template>
</v-data-table>
</div>
</template>
<script>
const desserts = [
{
name: "Frozen Yogurt",
calories: 200,
fat: 6.0,
},
{
name: "Ice cream sandwich",
calories: 200,
fat: 9.0,
},
{
name: "Eclair",
calories: 300,
fat: 16.0,
},
];
export default {
name: "HelloWorld",
data: () => ({
enabled: null,
search: null,
slots: [
"body",
"body.append",
"body.prepend",
"footer",
"header.data-table-select",
"header",
"progress",
"item.data-table-select",
"item.<name>",
"no-data",
"no-results",
"top",
],
headers: [
{
text: "Dessert (100g serving)",
align: "start",
sortable: false,
value: "name",
},
{ text: "Calories", value: "calories" },
{ text: "Fat (g)", value: "fat" },
],
items: desserts,
}),
computed: {
showSelect() {
return (
this.isEnabled("header.data-table-select") ||
this.isEnabled("item.data-table-select")
);
},
hideHeaders() {
return !this.showSelect;
},
isLoading() {
return this.isEnabled("progress");
},
},
watch: {
enabled(slot) {
if (slot === "no-data") {
this.items = [];
} else if (slot === "no-results") {
this.search = "...";
} else {
this.search = null;
this.items = desserts;
}
},
},
methods: {
isEnabled(slot) {
return this.enabled === slot;
},
},
};
</script>
We add the template
elements with the slots.
There are many slots for the body, showing data when there’s no data or no results, a footer, and more.
The dropdown sets which one is enabled and we use v-show
to show the enabled ones.
Conclusion
We can populate various slots with our own content.
Footer icons can also be changed.