V-data-table selection checkboxes initially on, using custom row template - vue.js

I'm using a custom template for each row in a v-data-table and I am trying to have checkboxes working for each row. For some reason if i use :value="item" all checkboxes are initially checked. I am not sure how it should be done. I want them not-to-be checked initially... When selecting, complete item should be added to selected. Also, on v-data-table I have show-select and this (de)select all checkbox must work. This is the case but initially I now have to use it before the checkboxes for the rows actually work.
<template #item="{ item }">
<tr>
<td>
<v-checkbox v-model="selected" :value="item"></v-checkbox>
</td>
<td v-for="field in fields" v-bind:key="field.id">{{ item[field.value] }}
</td>

You can simply achieve that without creating a separate template for the checkboxes.
Live Demo :
new Vue({
el: '#app',
vuetify: new Vuetify(),
data () {
return {
singleSelect: false,
selected: [],
headers: [
{
text: 'Dessert (100g serving)',
align: 'start',
sortable: false,
value: 'name',
},
{ text: 'Calories', value: 'calories' },
{ text: 'Fat (g)', value: 'fat' },
{ text: 'Carbs (g)', value: 'carbs' },
{ text: 'Protein (g)', value: 'protein' },
{ text: 'Iron (%)', value: 'iron' },
],
desserts: [
{
name: 'Frozen Yogurt',
calories: 159,
fat: 6.0,
carbs: 24,
protein: 4.0,
iron: '1%',
},
{
name: 'Ice cream sandwich',
calories: 237,
fat: 9.0,
carbs: 37,
protein: 4.3,
iron: '1%',
},
{
name: 'Eclair',
calories: 262,
fat: 16.0,
carbs: 23,
protein: 6.0,
iron: '7%',
},
],
}
},
})
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.2.30/dist/vuetify.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vuetify#2.2.30/dist/vuetify.min.css"/>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900"/>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css"/>
<div id="app">
<v-app id="inspire">
<h5>Selected: {{selected}}</h5>
<v-data-table
v-model="selected"
:headers="headers"
:items="desserts"
item-key="name"
show-select
class="elevation-1"
>
</v-data-table>
</v-app>
</div>
Updated : Below is the demo based on the custom template as per the author demand.
new Vue({
el: '#app',
vuetify: new Vuetify(),
data () {
return {
singleSelect: false,
selected: [],
headers: [
{
text: 'Dessert (100g serving)',
align: 'start',
sortable: false,
value: 'name',
},
{ text: 'Calories', value: 'calories' },
{ text: 'Fat (g)', value: 'fat' },
{ text: 'Carbs (g)', value: 'carbs' },
{ text: 'Protein (g)', value: 'protein' },
{ text: 'Iron (%)', value: 'iron' },
],
desserts: [
{
name: 'Frozen Yogurt',
calories: 159,
fat: 6.0,
carbs: 24,
protein: 4.0,
iron: '1%',
},
{
name: 'Ice cream sandwich',
calories: 237,
fat: 9.0,
carbs: 37,
protein: 4.3,
iron: '1%',
},
{
name: 'Eclair',
calories: 262,
fat: 16.0,
carbs: 23,
protein: 6.0,
iron: '7%',
},
],
}
},
})
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.2.30/dist/vuetify.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vuetify#2.2.30/dist/vuetify.min.css"/>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900"/>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css"/>
<div id="app">
<v-app id="inspire">
<h5>Selected: {{selected}}</h5>
<v-data-table
v-model="selected"
:headers="headers"
:items="desserts"
item-key="name"
show-select
class="elevation-1"
>
<template v-slot:items="item">
<tr>
<td>
<v-checkbox v-model="selected" :value="item"></v-checkbox>
</td>
<td v-for="field in Object.keys(item)" v-bind:key="item[field]">{{ item[field] }}
</td>
</tr>
</template>
</v-data-table>
</v-app>
</div>

Related

How to change `Items per page` text in vuetify?

I am trying to translate the text of items per page in a v-data-table. I have translated successfully rows per page text but I am not able to change items per page text. I have tried this:
<v-data-table
:items-per-page="itemsPerPage"
:footer-props="{'items-per-page-text': this.$i18n.t('rowsPerPage'), 'page-text': this.$i18n.t('itemsPerPage')}"
:headers="headers"
:items="items"
>
Data:
itemsPerPage: 10,
But any of them worked.
You can use external pagination to change text.
<template>
<div>
<v-data-table
:headers="headers"
:items="desserts"
:page.sync="page"
:items-per-page="itemsPerPage"
hide-default-footer
class="elevation-1"
#page-count="pageCount = $event"
></v-data-table>
<div class="text-center pt-2">
<v-pagination
v-model="page"
:length="pageCount"
></v-pagination>
<div class='d-flex align-center'>
<!-- you can write your text here according to your requirements -->
<span>Items per page </span>
<v-select
v-model="itemsPerPage"
:items="perPageValues"
></v-select>
</div>
</div>
</div>
</template>
<script>
export default {
data () {
return {
page: 1,
pageCount: 0,
itemsPerPage: 5,
perPageValues:[5, 10, 15, 20],
headers: [
{
text: 'Dessert (100g serving)',
align: 'start',
sortable: false,
value: 'name',
},
{ text: 'Calories', value: 'calories' },
{ text: 'Fat (g)', value: 'fat' },
{ text: 'Carbs (g)', value: 'carbs' },
{ text: 'Protein (g)', value: 'protein' },
{ text: 'Iron (%)', value: 'iron' },
],
desserts: [
{
name: 'Frozen Yogurt',
calories: 159,
fat: 6.0,
carbs: 24,
protein: 4.0,
iron: '1%',
},
{
name: 'Ice cream sandwich',
calories: 237,
fat: 9.0,
carbs: 37,
protein: 4.3,
iron: '1%',
}
],
}
},
}
</script>
You can use localeText object inside gridOptions object to translate ag-grid related in-built texts.
Official documentation : vue-data-grid localization
gridOptions: {
localeText: {
rowsPerPage: I18n.t('rowsPerPage').toString()
}
}

Vuetify rendering v-datatable automatically

I have a problem v-datatable rendering each time I change a v-select.
I´d like it render only when I click in a button, I created to do fetch data from server.
Here is the codepen: https://codepen.io/luizalves/pen/VwrwXwE?editors=101
For now, it´s rendering all times I change the v-select.
data:()=>({
grupos: [
{ id: 1, nome: 'Diário', ffi: 'YYYY-MM-DD', fff: 'DD-MM-YYYY' },
{ id: 2, nome: 'Mensal', ffi: 'YYYY-MM', fff: 'MM-YYYY' },
{ id: 3, nome: 'Anual', ffi: 'YYYY', fff: 'YYYY' },
],
grupo:1
headers: [
{ text: 'Data', value: 'label', sortable: false },
{ text: 'Total(R$) ', value: 'total', sortable: false },
],
)}
// data-table
<v-select
v-model="grupo"
label="Grupado por"
:items="grupos"
item-text="nome"
item-value="id"
class="purple-input"
/>
<v-btn
class="mt-1 mr-3"
color="info"
#click.stop="getEstatisticasPeriodo()"
>
Pesquisar
</v-btn>
<v-data-table
:headers="headers"
:items="result_dados"
:items-per-page="3"
:footer-props="{
'items-per-page-options': [3, 5, 10, 20, 30, 40, 50],
}"
class="elevation-1"
>
<template
v-for="(header, i) in headers"
#[`item.${header.value}`]="{ item }"
>
<template v-if="header.value !== 'actions'">
<span :key="i">
{{ formatColumn(item, header) }}
</span>
</template>
</template>
</v-data-table>
methods: {
formatColumn(item, col) {
if (!item[col.value]) return ''
if (['total'].includes(col.value)) {
const formatado = Number(item[col.value]).toLocaleString('pt-BR', {
style: 'currency',
currency: 'BRL',
})
return formatado
}
if (['label'].includes(col.value)) {
const ffi = this.grupos.find((m) => m.id == this.grupo).ffi
const fff = this.grupos.find((m) => m.id == this.grupo).fff
return this.$moment(item[col.value], ffi).format(fff)
} else return item[col.value]
},
getEstatisticasPeriodo(){
// fetch api data
}
....
Any data value you access in formatCalories will be added the list of watched values. When the value changes, it will re-render the view and call formatCalories. To solve that issue, I just created a selectValue property that is only set when the button is clicked.
new Vue({
el: '#app',
vuetify: new Vuetify(),
data () {
return {
group: 1,
selectValue: 1,
groups: [
{ id: 1, name: 'day'},
{ id: 2, name: 'month' },
{ id: 3, name: 'year' },
],
headers: [
{
text: 'Dessert (100g serving)',
align: 'start',
sortable: false,
value: 'name',
},
{ text: 'Calories', value: 'calories' },
{ text: 'Fat (g)', value: 'fat' },
{ text: 'Carbs (g)', value: 'carbs' },
{ text: 'Protein (g)', value: 'protein' },
{ text: 'Iron (%)', value: 'iron' },
],
desserts: [
{
name: 'Frozen Yogurt',
calories: 159,
fat: 6.0,
carbs: 24,
protein: 4.0,
iron: '1%',
},
{
name: 'Ice cream sandwich',
calories: 237,
fat: 9.0,
carbs: 37,
protein: 4.3,
iron: '1%',
},
{
name: 'Eclair',
calories: 262,
fat: 16.0,
carbs: 23,
protein: 6.0,
iron: '7%',
},
{
name: 'Cupcake',
calories: 305,
fat: 3.7,
carbs: 67,
protein: 4.3,
iron: '8%',
},
{
name: 'Gingerbread',
calories: 356,
fat: 16.0,
carbs: 49,
protein: 3.9,
iron: '16%',
},
{
name: 'Jelly bean',
calories: 375,
fat: 0.0,
carbs: 94,
protein: 0.0,
iron: '0%',
},
{
name: 'Lollipop',
calories: 392,
fat: 0.2,
carbs: 98,
protein: 0,
iron: '2%',
},
{
name: 'Honeycomb',
calories: 408,
fat: 3.2,
carbs: 87,
protein: 6.5,
iron: '45%',
},
{
name: 'Donut',
calories: 452,
fat: 25.0,
carbs: 51,
protein: 4.9,
iron: '22%',
},
{
name: 'KitKat',
calories: 518,
fat: 26.0,
carbs: 65,
protein: 7,
iron: '6%',
},
],
}
},
methods: {
onSubmit() {
this.selectValue = this.$refs.select.value;
},
formatCalories(calories) {
const suffix = {
1: '-red',
2: '-orange',
3: '-green'
};
return calories + suffix[this.selectValue];
}
},
})
<div id="app">
<v-app id="inspire">
<v-row>
<v-col cols='3'>
<v-btn elevation="2" #click="onSubmit"> Submit </v-btn>
<v-select
v-model="group"
label="Grouped by"
:items="groups"
item-text="name"
item-value="id"
class="purple-input"
ref="select"
/>
</v-col>
</v-row>
<v-data-table
:headers="headers"
:items="desserts"
class="elevation-1"
>
<template v-slot:item.calories="{ item }">
{{ formatCalories(item.calories) }}
</template>
</v-data-table>
</v-app>
</div>

Scroll to first selected row in v-data-table

I have a v-data-table that I highlight a selected row by adding a selectedRow class to the table row. After an update in another component the v-data-table is refreshed. I want it to automatically scroll back to the selected row. I'm getting an error that the element cannot be found. It seems to not be finding the CSS selector I am trying to pass as the target.
mounted: function () {
eventBus.$on("refreshVendors", () => {
this.getVendors();
// add scrollTo first selected vendor
this.$vuetify.goTo(".selectedRow");
});
this.clearSelectedVendors();
this.getVendors();
},
I've tried using next tick but same error occurs.
For current version=v2.3.6 now, The CSS class for selected row is v-data-table__selected, so changes that line to this.$nextTick(() => this.$vuetify.goTo('.v-data-table__selected')).
Below is one demo based on the snippet in official site:
PS: hit 'Goto' button at the end of the fiddle then you will see the effect.
new Vue({
el: '#app',
vuetify: new Vuetify(),
methods: {
gotoSelectedRow: function () {
this.desserts[1].selected = false
this.desserts[0].selected = true
this.$nextTick(() => this.$vuetify.goTo('.selectedRow'))
}
},
data () {
return {
headers: [
{
text: 'Dessert (100g serving)',
align: 'start',
sortable: false,
value: 'name',
},
{ text: 'Calories', value: 'calories' },
{ text: 'Fat (g)', value: 'fat' },
{ text: 'Carbs (g)', value: 'carbs' },
{ text: 'Protein (g)', value: 'protein' },
{ text: 'Iron (%)', value: 'iron' },
],
desserts: [
{
name: 'Frozen Yogurt',
calories: 159,
fat: 6.0,
carbs: 24,
protein: 4.0,
iron: '1%',
},
{
name: 'Ice cream sandwich',
calories: 237,
fat: 9.0,
carbs: 37,
protein: 4.3,
iron: '1%',
selected: true
},
{
name: 'Eclair',
calories: 262,
fat: 16.0,
carbs: 23,
protein: 6.0,
iron: '7%',
},
{
name: 'Cupcake',
calories: 305,
fat: 3.7,
carbs: 67,
protein: 4.3,
iron: '8%',
},
{
name: 'Gingerbread',
calories: 356,
fat: 16.0,
carbs: 49,
protein: 3.9,
iron: '16%',
},
{
name: 'Jelly bean',
calories: 375,
fat: 0.0,
carbs: 94,
protein: 0.0,
iron: '0%',
},
{
name: 'Lollipop',
calories: 392,
fat: 0.2,
carbs: 98,
protein: 0,
iron: '2%',
},
{
name: 'Honeycomb',
calories: 408,
fat: 3.2,
carbs: 87,
protein: 6.5,
iron: '45%',
},
{
name: 'Donut',
calories: 452,
fat: 25.0,
carbs: 51,
protein: 4.9,
iron: '22%',
},
{
name: 'KitKat',
calories: 518,
fat: 26.0,
carbs: 65,
protein: 7,
iron: '6%',
},
],
}
},
})
.selectedRow
{
color: red;
}
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#5.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/babel-polyfill/dist/polyfill.min.js"></script>
<div id="app">
<v-app id="inspire">
<v-data-table
:headers="headers"
:items="desserts"
item-key="name"
class="elevation-1"
>
<template v-slot:top>
<v-switch v-model="singleSelect" label="Single select" class="pa-3"></v-switch>
</template>
<template v-slot:body="{ items }">
<tbody>
<tr v-for="item in items" :key="item.name" :class="{'selectedRow': item.selected}">
<td>{{ item.name }}</td>
<td>{{ item.calories }}</td>
<td>{{ item.fat }}</td>
<td>{{ item.carbs }}</td>
<td>{{ item.protein }}</td>
<td>{{ item.iron }}</td>
</tr>
</tbody>
</template>
</v-data-table>
<button #click="gotoSelectedRow()">Goto</button>
</v-app>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>

How do I integrate checkboxes with v-data-table - Vuetify

I have a simple V-data-table. I am trying to add checkboxes for each row in the table.
My table looks like this.
<v-data-table :headers="headers" :items="rows"item-key="name" :search="search">
<template v-slot:item="props">
<tr >
<td v-for="(prop, key) in props.item" :key="key" #click="onClickItem(key, props.item[key])">
{{props.item[key]}}
</td>
<td>
<!-- Some icons for editing rows -->
</td>
</tr>
</template>
<template v-slot:top>
<!-- A dialog box for editing rows -->
</template>
</v-data-table>
I tried to use the official guide for doing this, however all my rows get shifted to the right by 1 position & I only see only one checkbox even though I have multiple rows, that too, on the header!
How should I proceed?
Here is the working codepen similar to official doc
https://codepen.io/manojkmishra/pen/MWadELG
another way
https://codepen.io/manojkmishra/pen/bGVyoaw
TEMPLATE PART:
<div id="app">
<v-app id="inspire">
<h5>Selected: {{selected}}</h5>
<v-data-table
v-model="selected"
:headers="headers"
:items="desserts"
item-key="name"
show-select
class="elevation-1"
>
</v-data-table>
</v-app>
</div>
SCRIPT PART:
new Vue({
el: '#app',
vuetify: new Vuetify(),
data () {
return {
singleSelect: false,
selected: [],
headers: [
{
text: 'Dessert (100g serving)',
align: 'start',
sortable: false,
value: 'name',
},
{ text: 'Calories', value: 'calories' },
{ text: 'Fat (g)', value: 'fat' },
{ text: 'Carbs (g)', value: 'carbs' },
{ text: 'Protein (g)', value: 'protein' },
{ text: 'Iron (%)', value: 'iron' },
],
desserts: [
{
name: 'Frozen Yogurt',
calories: 159,
fat: 6.0,
carbs: 24,
protein: 4.0,
iron: '1%',
},
{
name: 'Ice cream sandwich',
calories: 237,
fat: 9.0,
carbs: 37,
protein: 4.3,
iron: '1%',
},
{
name: 'Eclair',
calories: 262,
fat: 16.0,
carbs: 23,
protein: 6.0,
iron: '7%',
},
],
}
},
})

Vuetify data table mobile breakpoint

I have this vuetify data-table and I Want keep the same behavior on mobile resizing.
So I just want all in data on the same line.
https://codepen.io/sebastiancz/pen/JjoVRVg?editable=true&editors=101
<div id="app">
<v-app id="inspire">
<v-data-table
:headers="headers"
:items="desserts"
:items-per-page="5"
class="elevation-1"
></v-data-table>
</v-app>
</div>
new Vue({
el: '#app',
vuetify: new Vuetify(),
data () {
return {
headers: [
{
text: 'Dessert (100g serving)',
align: 'left',
sortable: false,
value: 'name',
},
{ text: 'Calories', value: 'calories' },
{ text: 'Fat (g)', value: 'fat' },
{ text: 'Carbs (g)', value: 'carbs' },
],
desserts: [
{
name: 'Frozen Yogurt',
calories: 159,
fat: 6.0,
carbs: 24
},
{
name: 'Ice cream sandwich',
calories: 237,
fat: 9.0,
carbs: 37
}
],
}
},
})
You can use the mobile-breakpoint prop to configure this. Value of 0 seems to disable different mobile rendering.
<v-data-table
:headers="headers"
:items="desserts"
:items-per-page="5"
class="elevation-1"
mobile-breakpoint="0"
></v-data-table>