How to Build Dynamic Data Table in Vue 2 with Vuetify
We will also look at how to add data sorting and filtering feature very easily in Vue js.
What is Data Table?
A table is a classification of data in rows and columns, or probably in a more complicated structure.
Tables are extensively used for data analysis, communication, and research and can be used in various domains such as print media, computer software, architectural elaboration, traffic signs, and many other places.
Data tables illustrate information in a more organizable manner in a grid-like composition that contains rows and columns. The architecture of a table is such that a user can quickly scan the displayed information.
A data table organizes information using column and rows, and a general DataTable has the following components:
- Columns
- Column header names
- Rows
- Footers
- Pagination
Getting Started
Create Vue project by using the following command.
vue create vue-data-table
Get inside the project directory.
cd vue-data-table
Node.js Gatsby error – “digital envelope routines::unsupported …”
Error: digital envelope routines::unsupported
opensslErrorStack: [ 'error:03000086:digital envelope routines::initialization error' ],
library: 'digital envelope routines',
reason: 'unsupported',
code: 'ERR_OSSL_EVP_UNSUPPORTED'
To remove above error for invoking the app, make sure to update the "scripts": []
array in package.json file.
"scripts": {
"serve": "export NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service serve",
"build": "export NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service build",
"lint": "export NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service lint"
},
Vue multi word error
To remove multi-word error warning, add the following code in vue.config.js file.
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
lintOnSave: false,
})
Install & Configure Vuetify Plugin
Creating a user-friendly application is a challenge in real-world. Vuetify is a powerful Vue UI Library with beautifully handcrafted Material Design UI Components. Vuetify offers 100% support for Vue, and comes with cleaner, semantic, and reusable UI components that lets you create a beautiful user interface in very less time..
You can use the following command to install Vuetify plugin in Vue.
npm install vuetify
Enable the Vuetify package globally in Vue by adding the following code in the main.js
.
// main.js
import Vue from 'vue'
import App from './App.vue'
import Vuetify from "vuetify";
import "vuetify/dist/vuetify.min.css";
Vue.use(Vuetify);
new Vue({
render: h => h(App)
}).$mount('#app')
Open public/index.html
file and add the Google fonts and Material Design Icons CSS in Vue app.
<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@4.x/css/materialdesignicons.min.css" rel="stylesheet">
Vuetify Simple Table Example in Vue
The v-simple-table directive creates the table component in Vue; it needs to be placed inside your Vue component and should be wrapped with the table tag.
<template>
<v-simple-table>
<template v-slot:default>
<thead>
<tr>
<th class="text-left">Name</th>
<th class="text-left">Calories</th>
</tr>
</thead>
<tbody>
<tr v-for="food in FOOD" :key="food.name">
<td>{{ food.name }}</td>
<td>{{ food.calories }}</td>
</tr>
</tbody>
</template>
</v-simple-table>
</template>
<script>
export default {
data () {
return {
FOOD: [
{
name: 'Burger',
calories: 660,
},
{
name: 'Sandwich',
calories: 660,
},
{
name: 'Cheese Whopper',
calories: 790,
},
{
name: 'Bacon King',
calories: 1150,
},
{
name: 'Farmhouse',
calories: 1220,
},
{
name: 'Grilled Chicken',
calories: 470,
},
{
name: 'Snickers Pie',
calories: 300,
},
{
name: 'Veggie Burger',
calories: 390,
},
{
name: 'Donut',
calories: 500,
},
{
name: 'Grilled Hot Dog',
calories: 310,
},
{
name: 'French Fry',
calories: 380,
},
],
}
},
}
</script>
FOOD is an array that contains some dummy food data in JSON format. The v-for
directive is iterating FOOD array and displaying the data with the table component.
Fixed Header Table Example
We should add the fixed-header property along with height property in v-simple-table
directive to make the table header fixed.
<template>
<v-simple-table fixed-header height="400px">
<template v-slot:default>
<thead>
<tr>
<th class="text-left">Name</th>
<th class="text-left">Calories</th>
</tr>
</thead>
<tbody>
<tr v-for="food in FOOD" :key="food.name">
<td>{{ food.name }}</td>
<td>{{ food.calories }}</td>
</tr>
</tbody>
</template>
</v-simple-table>
</template>
<script>
export default {
data () {
return {
FOOD: [
{
name: 'Burger',
calories: 660,
},
{
name: 'Sandwich',
calories: 660,
},
{
name: 'Cheese Whopper',
calories: 790,
},
{
name: 'Bacon King',
calories: 1150,
},
{
name: 'Farmhouse',
calories: 1220,
},
{
name: 'Grilled Chicken',
calories: 470,
},
{
name: 'Snickers Pie',
calories: 300,
},
{
name: 'Veggie Burger',
calories: 390,
},
{
name: 'Donut',
calories: 500,
},
{
name: 'Grilled Hot Dog',
calories: 310,
},
{
name: 'French Fry',
calories: 380,
},
],
}
},
}
</script>
Table Dark theme
To update the table current theme to dark theme can be done by just adding dark
tag to v-simple-table component.
<template>
<v-simple-table dark>
<template v-slot:default>
<thead>
<tr>
<th class="text-left">Name</th>
<th class="text-left">Calories</th>
</tr>
</thead>
<tbody>
<tr v-for="food in FOOD" :key="food.name">
<td>{{ food.name }}</td>
<td>{{ food.calories }}</td>
</tr>
</tbody>
</template>
</v-simple-table>
</template>
<script>
export default {
data () {
return {
FOOD: [...],
}
},
}
</script>
Here is how the table looks in Vue when updated to dark theme.
Build Data Table in Vue.js
Next, we are going to create Data Table in Vue using Vuetify plugin. The v-data-table
component is recommended for showing data in the table form. It comes with some of the core features of DataTable, such as sorting, searching, pagination, inline-editing, and row selection.
<template>
<v-data-table dark
:headers="headers"
:items="food"
:items-per-page="7"
class="elevation-1"
></v-data-table>
</template>
<script>
export default {
data () {
return {
headers: [
{
text: 'Food Items (Nutrition 100g)',
align: 'start',
sortable: false,
value: 'name',
},
{ text: 'Energy', value: 'energy' },
{ text: 'Protein', value: 'protein' },
{ text: 'Fat', value: 'fat' },
{ text: 'Carbohydrate', value: 'carbohydrate' },
{ text: 'Sodium', value: 'sodium' },
],
food: [
{
name: 'Muesli (Almond)',
energy: 201,
protein: 5.0,
fat: 34,
carbohydrate: 5.5,
sodium: '1.5%'
},
{
name: 'Wholegrain Rolled Oats',
energy: 301,
protein: 3.0,
fat: 54,
carbohydrate: 3.5,
sodium: '2.5%'
},
{
name: 'Almond Milk',
energy: 130,
protein: 6.0,
fat: 24,
carbohydrate: 3.9,
sodium: '3.5%'
},
{
name: 'Firm Tofu',
energy: 101,
protein: 2.0,
fat: 25,
carbohydrate: 2.1,
sodium: '0.5%'
},
{
name: 'Hummus',
energy: 709,
protein: 8.4,
fat: 10.8,
carbohydrate: 4.6,
sodium: '2.5%'
},
{
name: 'Peanut Butter',
energy: 2580,
protein: 28,
fat: 50,
carbohydrate: 12,
sodium: '3.5%'
},
{
name: 'Tahini',
energy: 2760,
protein: 25.0,
fat: 57.3,
carbohydrate: 12,
sodium: '7.0%'
},
{
name: 'Butter Beans',
energy: 384,
protein: 7.4,
fat: 0.9,
carbohydrate: 15.2,
sodium: '3.1%'
},
{
name: 'Chickpeas',
energy: 391,
protein: 5.0,
fat: 34,
carbohydrate: 5.5,
sodium: '2.3%'
},
{
name: 'Lentils',
energy: 290,
protein: 4.2,
fat: 0.9,
carbohydrate: 15,
sodium: '1.0%'
}
],
}
},
}
</script>
TypeError: Cannot read property ‘width’ of undefined
To get rid from the width undefined Vuetify error, we must define vuetify library to mounting function in main.js
file as mentioned below.
import Vue from 'vue'
import App from './App.vue'
import Vuetify from 'vuetify'
import "vuetify/dist/vuetify.min.css";
Vue.use(Vuetify)
new Vue({
vuetify: new Vuetify(),
render: h => h(App)
}).$mount('#app')
Search DataTable in Vue
Add a search prop to enable filtering feature in Data Tables is very easy in Vue with Vuetify.js.
<template>
<v-card>
<v-card-title>
Food Data
<v-spacer></v-spacer>
<v-text-field
v-model="search"
append-icon="mdi-magnify"
label="Search"
single-line
hide-details
></v-text-field>
</v-card-title>
<v-data-table
:headers="headers"
:items="food"
:search="search"
></v-data-table>
</v-card>
</template>
<script>
export default {
data () {
return {
search: '',
headers: [
{
text: 'Food Items (Nutrition 100g)',
align: 'start',
sortable: false,
value: 'name',
},
{ text: 'Energy', value: 'energy' },
{ text: 'Protein', value: 'protein' },
{ text: 'Fat', value: 'fat' },
{ text: 'Carbohydrate', value: 'carbohydrate' },
{ text: 'Sodium', value: 'sodium' },
],
food: [
{
name: 'Muesli (Almond)',
energy: 201,
protein: 5.0,
fat: 34,
carbohydrate: 5.5,
sodium: '1.5%'
},
{
name: 'Wholegrain Rolled Oats',
energy: 301,
protein: 3.0,
fat: 54,
carbohydrate: 3.5,
sodium: '2.5%'
},
{
name: 'Almond Milk',
energy: 130,
protein: 6.0,
fat: 24,
carbohydrate: 3.9,
sodium: '3.5%'
},
{
name: 'Firm Tofu',
energy: 101,
protein: 2.0,
fat: 25,
carbohydrate: 2.1,
sodium: '0.5%'
},
{
name: 'Hummus',
energy: 709,
protein: 8.4,
fat: 10.8,
carbohydrate: 4.6,
sodium: '2.5%'
},
{
name: 'Peanut Butter',
energy: 2580,
protein: 28,
fat: 50,
carbohydrate: 12,
sodium: '3.5%'
},
{
name: 'Tahini',
energy: 2760,
protein: 25.0,
fat: 57.3,
carbohydrate: 12,
sodium: '7.0%'
},
{
name: 'Butter Beans',
energy: 384,
protein: 7.4,
fat: 0.9,
carbohydrate: 15.2,
sodium: '3.1%'
},
{
name: 'Chickpeas',
energy: 391,
protein: 5.0,
fat: 34,
carbohydrate: 5.5,
sodium: '2.3%'
},
{
name: 'Lentils',
energy: 290,
protein: 4.2,
fat: 0.9,
carbohydrate: 15,
sodium: '1.0%'
}
],
}
},
}
</script>
Start the app in the browser.
npm run serve
Summary
Finally, we have completed the Vue Table tutorial with various examples, and i hope you liked this tutorial.
To know more about Vuetify, please check out their official documentation here.