Hello i need to hide or show columns of my datatable, I do not know what the good practice to do this, When columns checkboxes is checked the columns will shown and if it's not checked the column will be hidden? I'm using vuetify https://codepen.io/anon/pen/rmXwYG?editors=1010
This my script :
new Vue({
el: '#app',
data() {
return {
search: '',
totalItems: 0,
items: [],
loading: true,
pagination: {},
columns: [],
headers: [{
text: 'Dessert (100g serving)',
left: true,
sortable: false,
value: 'name'
},
{
text: 'Calories',
value: 'calories'
},
{
text: 'Fat (g)',
value: 'fat'
},
{
text: 'Carbs (g)',
value: 'carbs'
},
{
text: 'Protein (g)',
value: 'protein'
},
{
text: 'Sodium (mg)',
value: 'sodium'
},
{
text: 'Calcium (%)',
value: 'calcium'
},
{
text: 'Iron (%)',
value: 'iron'
}
]
}
},
watch: {
pagination: {
handler() {
this.getDataFromApi()
.then(data => {
this.items = data.items
this.totalItems = data.total
})
},
deep: true
}
},
mounted() {
this.getDataFromApi()
.then(data => {
this.items = data.items
this.totalItems = data.total
})
},
methods: {
getDataFromApi() {
this.loading = true
return new Promise((resolve, reject) => {
const {
sortBy,
descending,
page,
rowsPerPage
} = this.pagination
let items = this.getUsers()
const total = items.length
if (this.pagination.sortBy) {
items = items.sort((a, b) => {
const sortA = a[sortBy]
const sortB = b[sortBy]
if (descending) {
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 (rowsPerPage > 0) {
items = items.slice((page - 1) * rowsPerPage, page * rowsPerPage)
}
setTimeout(() => {
this.loading = false
resolve({
items,
total
})
}, 1000)
})
},
getUsers() {
return [{
value: false,
name: 'Frozen Yogurt',
calories: 159,
fat: 6.0,
carbs: 24,
protein: 4.0,
sodium: 87,
calcium: '14%',
iron: '1%'
},
{
value: false,
name: 'Ice cream sandwich',
calories: 237,
fat: 9.0,
carbs: 37,
protein: 4.3,
sodium: 129,
calcium: '8%',
iron: '1%'
},
{
value: false,
name: 'Eclair',
calories: 262,
fat: 16.0,
carbs: 23,
protein: 6.0,
sodium: 337,
calcium: '6%',
iron: '7%'
},
{
value: false,
name: 'Cupcake',
calories: 305,
fat: 3.7,
carbs: 67,
protein: 4.3,
sodium: 413,
calcium: '3%',
iron: '8%'
},
{
value: false,
name: 'Gingerbread',
calories: 356,
fat: 16.0,
carbs: 49,
protein: 3.9,
sodium: 327,
calcium: '7%',
iron: '16%'
},
{
value: false,
name: 'Jelly bean',
calories: 375,
fat: 0.0,
carbs: 94,
protein: 0.0,
sodium: 50,
calcium: '0%',
iron: '0%'
},
{
value: false,
name: 'Lollipop',
calories: 392,
fat: 0.2,
carbs: 98,
protein: 0,
sodium: 38,
calcium: '0%',
iron: '2%'
},
{
value: false,
name: 'Honeycomb',
calories: 408,
fat: 3.2,
carbs: 87,
protein: 6.5,
sodium: 562,
calcium: '0%',
iron: '45%'
},
{
value: false,
name: 'Donut',
calories: 452,
fat: 25.0,
carbs: 51,
protein: 4.9,
sodium: 326,
calcium: '2%',
iron: '22%'
},
{
value: false,
name: 'KitKat',
calories: 518,
fat: 26.0,
carbs: 65,
protein: 7,
sodium: 54,
calcium: '12%',
iron: '6%'
}
]
}
}
})
Short answer is use computed properties to decide what columns are going to be included.
Your data table is taking a list of headers and a list of items (rows). I've added a couple of computed properties to your Vue to return the list of columns that should be included in the data table results.
computed:{
filteredHeaders(){
return this.headers.filter(h => h.selected)
},
filteredItems(){
return this.items.map(item => {
let filtered = Object.assign({}, item)
this.headers.forEach(header => {
if (!header.selected) delete filtered[header.value]
})
return filtered
})
}
},
Notice that these computed values are using a property of the header called selected
. I added that property to your list of headers to allow you to select the headers that are going to be included in the output.
{
text: 'Fat (g)',
value: 'fat',
selected: true
},
Next, your checkboxes need to use that property as their model.
<v-checkbox v-bind:label="header.text" v-model="header.selected" :value="header.selected" ></v-checkbox>
Finally, you have a template for each row. I modified that to check to see if each column is enabled.
<template slot="items" scope="props">
<td v-if="showColumn('name')">{{ props.item.name }}</td>
<td v-if="showColumn('calories')" class="text-xs-right">{{ props.item.calories }}</td>
<td v-if="showColumn('fat')" class="text-xs-right">{{ props.item.fat }}</td>
<td v-if="showColumn('carbs')" class="text-xs-right">{{ props.item.carbs }}</td>
<td v-if="showColumn('protein')" class="text-xs-right">{{ props.item.protein }}</td>
<td v-if="showColumn('sodium')" class="text-xs-right">{{ props.item.sodium }}</td>
<td v-if="showColumn('calcium')" class="text-xs-right">{{ props.item.calcium }}</td>
<td v-if="showColumn('iron')" class="text-xs-right">{{ props.item.iron }}</td>
</template>
And here is the showColumn
method that is used in that template.
showColumn(col){
return this.headers.find(h => h.value === col).selected
},
Finally, here is a working example.
Obviously this is not tuned or anything, it's just an initial "get it working" version. But it should get you going.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With