I have this simple table in Vuetify, without headers and only one column. How can I change it to vuetify v-data-table
?
<v-simple-table>
<thead />
<tbody>
<tr
v-for="item in categories"
:key="item"
@click="handleClick"
>
<td>{{ item }}</td>
<v-switch />
</tr>
</tbody>
</v-simple-table>
categories
is a simple array of strings. I want to change it to data-table in order to nicely handle clicking and selecting rows.
CodePudding user response:
You can change like this :
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
categoryList: ['Category 1', 'Category 2', 'Category 3'],
}),
computed: {
categoriesHeader() {
return [
{ text: "Name", value: "name" }
];
},
},
})
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.min.css" rel="stylesheet">
<div id="app">
<v-app id="a">
<v-data-table :headers="categoriesHeader" :items="categoryList" item-key="id" >
<template v-slot:[`item.name`]="{ item }">
{{ item }}
</template>
</v-data-table>
</v-app>
</div>
CodePudding user response:
Check this codesandbox I made: https://codesandbox.io/s/stack-71617004-simple-to-v-data-table-bm2yn1?file=/src/components/Example.vue
Using body slot
You can use the body
slot of the data table and use almost the same code you have in your simple table like this. This way you set up the handleClick function in the tr
:
<v-data-table
:headers="headers"
:items="items"
hide-default-footer
hide-default-header
:items-per-page="-1"
:footer-props="{
itemsPerPageOptions: [-1],
}"
>
<template v-slot:body="{ items}">
<tbody>
<tr v-for="item in items" :key="item" @click="handleClick(item)">
<td align="left">{{item}}</td>
</tr>
</tbody>
</template>
</v-data-table>
Using item slot
Or you can use the item
slot, like this. In this other way, the handleClick function is configured using the @click:row
event of the data table.
If you try to use the item
slot with your array of strings, it will work but you'll get some warnings in your console. Telling you that your data-table item slot expected an object and received an string. That's because v-data-table
component expects to receive an array of objects.
To avoid this warning you can simply convert your array of string into a dummy array of objects using Array.prototype.map, and bind the computed property instead.
computed: {
myItemsTransformed() {
return this.items.map(item => ({ name: item }));
}
},
<v-data-table
:headers="headers"
:items="myItemsTransformed"
hide-default-footer
hide-default-header
:items-per-page="-1"
:footer-props="{
itemsPerPageOptions: [-1],
}"
@click:row="(item) => handleClick(item.name)"
>
<template #item.name="{ item }">
{{ item.name }}
</template>
</v-data-table>
Notice that in both examples I have used the props hide-default-footer
, hide-default-header
to hide the footer and header of the data table and also set the items-per-page
to -1
. To show all the items of the table and avoid the pagination.