In my Vuetifyjs projects, we use pretty advanced data grids. Advanced in a sense of, it has buttons and menu items. Something is bothering me a bit in the rendering performance for the grids which contains buttons and menu items. In some cases it takes up to 700ms to render the advance grids with about 40-50 records.
Question: What can I do to improve rendering speed?
Known Solution: Obvious solution is to have 10 records per page, but for now that is last resort
Side Note: Normal grids with no buttons and menus items performance is fine
Take a look at my codepen example. Its still pretty simple and you can cleary see the slow rendering when clearing the data en show it again.
<div id="app">
<v-app id="inspire">
Total Records: {{desserts.length}}
<v-btn #click="cleanData()">Clean Data</v-btn>
<v-btn #click="resetData()">Reset Data</v-btn>
<v-data-table :headers="headers" :items="desserts" class="elevation-1" hide-actions>
<template slot="items" slot-scope="props">
<td>{{ props.item.name }}</td>
<td class="text-xs-right">{{ props.item.calories }}</td>
<td class="text-xs-right">{{ props.item.fat }}</td>
<td class="text-xs-right">{{ props.item.carbs }}</td>
<td class="text-xs-right">{{ props.item.protein }}</td>
<td class="text-xs-right">{{ props.item.iron }}</td>
<td class="text-xs-right">
<v-menu bottom origin="center center" transition="scale-transition" offset-y>
<v-btn color="secondary" medium slot="activator">
<v-icon>more_horiz</v-icon>
</v-btn>
<v-list>
<v-list-tile v-for="item in menuItems" :key="item">
<v-list-tile-title>{{ item }}</v-list-tile-title>
</v-list-tile>
</v-list>
</v-menu>
<v-tooltip top>
<v-btn
color="success"
slot="activator"
medium
#click.stop="
"
>
<v-icon>arrow_forward</v-icon>
</v-btn>
<span>Move to next status</span>
</v-tooltip>
</td>
</template>
</v-data-table>
</v-app>
</div>
Related
I'm trying to show all the users that I have in Firebase, inside a v-data-table, but all the rows are shown in a single row.
<v-data-table
:headers="headers"
:items="users"
:loading="loading"
class="elevation-1"
:no-data-text="$t('admin.usersTable.empty')"
>
<template slot="item" slot-scope="props">
<td class="text-xs-right">{{ props.item.uid }}</td>
<td class="text-xs-right">{{ props.item.email }}</td>
<td class="text-xs-right">{{ props.item.username }}</td>
<td class="justify-center layout px-0">
<v-btn icon class="mx-0" #click="editUser(props.item)">
<v-icon color="teal">edit</v-icon>
</v-btn>
<v-btn icon class="mx-0" #click="removeUser(props.item)">
<v-icon color="pink">delete</v-icon>
</v-btn>
</td>
</template>
</v-data-table>
I expect the three users in a three different rows, but the result is that I have the users in one row
Maybe you should add a "s" in the word "item" ?
Like that :
<template slot="items" slot-scope="props">
rows per page is not working correctly, it locates at right side how can I fix it? firstly it didn't show then I added and in console it showed warning, than I added app-data = "true" then it was fixed, but dropdown didn't work correctly.
<template>
<div app-data="true">
<v-app id="app">
<v-content>
<v-card>
<v-card-title>
Nutrition
<v-spacer></v-spacer>
<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"
>
<template v-slot:items="props">
<td>{{ props.item.name }}</td>
<td class="text-xs-right">{{ props.item.calories }}</td>
<td class="text-xs-right">{{ props.item.fat }}</td>
<td class="text-xs-right">{{ props.item.carbs }}</td>
<td class="text-xs-right">{{ props.item.protein }}</td>
<td class="text-xs-right">{{ props.item.iron }}</td>
</template>
<template v-slot:no-results>
<v-alert :value="true" color="error" icon="warning">
Your search for "{{ search }}" found no results.
</v-alert>
</template>
</v-data-table>
</v-card>
</v-content>
</v-app>
</div>
</template>
I have the following code:
<v-app>
<v-content>
<v-container fluid full-height>
<v-layout row wrap>
<v-flex xs12>
<v-data-table
hide-actions
:headers='headers'
:items='items'
class='elevation-1'
></v-data-table>
</v-flex>
</v-layout>
</v-container>
</v-content>
</v-app>
in the script section:
data: {
headers: [
{text: 'Name', value: 'name'},
{text: 'Age', value: 'age'}
],
items: [
{
name: 'John',
age: 30
}
]
}
https://jsfiddle.net/eywraw8t/507618/
I do not understand why I'm just getting the header of the table and not the data.
Can someone help me?
You have to define your table cells within the "items" slot of the v-data-table component. Headers render automatically, you can specify a "header" slot from customer headers. Checkout out this codepen from the Vuetify Docs on datatables. Notice the template within the v-data-table element that is defining the "items" slot.
<template>
<v-data-table
:headers="headers"
:items="desserts"
class="elevation-1"
>
<template slot="items" slot-scope="props">
<td>{{ props.item.name }}</td>
<td class="text-xs-right">{{ props.item.calories }}</td>
<td class="text-xs-right">{{ props.item.fat }}</td>
<td class="text-xs-right">{{ props.item.carbs }}</td>
<td class="text-xs-right">{{ props.item.protein }}</td>
<td class="text-xs-right">{{ props.item.iron }}</td>
</template>
</v-data-table>
</template>
Just define a slot with your table cells. In your code you have already added items props. You need to populate items inside a slot with data-table cells.
Here is your code with new changes.
<v-app>
<v-content>
<v-container fluid full-height>
<v-layout row wrap>
<v-flex xs12>
<v-data-table
hide-actions
:headers='headers'
:items='items'
class='elevation-1'
>
<template slot="items" slot-scope="props">
<td>{{ props.item.name }}</td>
<td class="text-xs-right">{{ props.item.age }}</td>
</template>
</v-data-table>
</v-flex>
</v-layout>
</v-container>
</v-content>
</v-app>
If you need more information read the docs
Hope this helps.
I have the following table in which I can't align some items such as the checkbox and the actions:
This is the table:
<v-data-table
:headers="headers"
:items="users"
hide-actions
class="elevation-1"
>
<template slot="items" slot-scope="props">
<td>{{ props.item.email }}</td>
<td class="text-xs-left">{{ props.item.empresa.descripcion}}</td>
<v-checkbox disabled v-model="props.item.isAdmin"></v-checkbox>
<td class="text-xs-left">{{ props.item.createdAt }}</td>
<td class="justify-center layout px-0">
<v-icon
small
class="mr-2"
#click="editItem(props.item)"
>
Editar
</v-icon>
<v-icon
small
left
class="mr-2"
#click="deleteItem(props.item)"
>
Eliminar
</v-icon>
</td>
</template>
</v-data-table>
I need to align the v-checkbox and the v-icon.
There is no css in the <style> section.
Give it a try wrapping the <v-layout justify-center></v-layout> with <td></td> like the Ohgodwhy comment.
It would be like:
<v-data-table
:headers="headers"
:items="users"
hide-actions
class="elevation-1"
>
<template slot="items" slot-scope="props">
<td>
<v-layout justify-center>
{{ props.item.email }}
</v-layout>
</td>
<td>
<v-layout justify-center>
{{ props.item.empresa.descripcion}}
</v-layout>
</td>
<td>
<v-layout justify-center>
<v-checkbox disabled v-model="props.item.isAdmin"></v-checkbox>
</v-layout>
</td>
<td>
<v-layout justify-center>
{{ props.item.createdAt }}
</v-layout>
</td>
<td>
<v-layout justify-center>
<v-icon
small
class="mr-2"
#click="editItem(props.item)"
>
Editar
</v-icon>
<v-icon
small
left
class="mr-2"
#click="deleteItem(props.item)"
>
Eliminar
</v-icon>
</v-layout>
</td>
</template>
</v-data-table>
For those of you taking a simple example from the Vuetify docs like I did:
<v-card>
<v-card-title id="balloon-title">Balloon Info - tracking [balloon ID]</v-card-title>
<v-data-table disable-sort dense hide-default-footer :headers="headers" :items="info" item-key="name">
</v-data-table>
</v-card>
The solution above requires you to change your entire layout. Instead, I styled the td selector like so
td {
text-align: center !important;
}
Hope this helps!
edit- make sure this style isn't in a scoped component.
Here's a simplified snippet that iterates <td> instead of specifying each prop, using only the css class text-center instead of a whole v-layout component:
<v-data-table
item-key="yourItemKey"
:items="dataSet"
:headers="headers">
<!-- item is the row itself with the column values -->
<template v-slot:item="{ item }">
<tr>
<td v-for="(val, key) in item" :key="key" class="text-center">
{{ val }}
</td>
</tr>
</template>
</v-data-table>
Table:
<v-card :dark="true">
<v-card-title>
<v-btn color="indigo" dark #click="initialize"><v-icon dark>refresh</v-icon></v-btn>
<v-spacer></v-spacer>
<v-text-field append-icon="search" label="Search" single-line hide-details></v-text-field>
</v-card-title>
<v-data-table :dark="true" :headers="headers" :items="expenses" hide-actions class="elevation-1">
<template slot="headers" slot-scope="props">
<tr>
<th v-for="header in props.headers">{{header.text}}</th>
</tr>
</template>
<template slot="items" slot-scope="props">
<tr v-bind:class="getClass(props.item)">
<td class="text-xs-center">{{ props.item.year }}</td>
<td class="text-xs-center">{{ props.item.month }}</td>
<td class="text-xs-center">{{ props.item.day }}</td>
<td class="text-xs-center">{{ props.item.description }}</td>
<td class="text-xs-center">{{ props.item.value }}</td>
<td class="text-xs-center">{{ props.item.category }}</td>
<td class="text-xs-center">{{ props.item.details }}</td>
<td class="justify-center layout px-0">
<v-btn icon class="mx-0" #click="deleteItem(props.item)">
<v-icon color="pink">delete</v-icon>
</v-btn>
</td>
</tr>
</template>
<template slot="no-data">
<v-btn color="primary" #click="initialize">Reset</v-btn>
</template>
</v-data-table>
</v-card>
Css before page reload, after the code is edited in Webstorm and automatically compiled:
And after the reload:
And if I just remove the first row, the same happens no matter which one is first.
I had the same problem.
They problem here is that You override the items slot including <tr> tag. Without that everything will work fine. But for me, that was not a solution so if You want to override the <tr> tag also, add :key to it, like this: <tr :key="props.index">.
Take a look at source of v-data-table here.
To be honest, i don't know why it make that big difference but in my case that resolved the problem (i suspect that it is connected with vue list rendering).
Hope it helps!