Vue 2 Tutorial- How To Build A Dynamic Data Table In Vue 2 With Vuetify

In this tutorial, we will learn how to build a customizable and pageable data table in the Vue application using the Vuetify plugin.

In addition, we will learn how to add data sorting and filtering features very easily in Vue.js.

Most of us already know that tables are the classification of data in rows and columns or probably in a more complicated structure.

 

Why are tables used?

Tables are generally used for data analysis, communication and research. It can be used in various domains such as print media, computer software, architectural elaboration, traffic signs and many other places.

Data tables help represent the information in a grid-like composition containing rows and columns.

A data table organizes information using columns and rows and a general DataTable has the following components:

  • Columns
  • Column header names
  • Rows
  • Footers
  • Pagination

Step 1- Creating Vue Project

In the very first step, we will create Vue project by using the below command:

vue create vue-data-table

Then, we get inside the project directory:

cd vue-data-table

 

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 the above error for invoking the app, we have to make sure to update the “scripts”: [] array in the 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"
},

 

Step 2- Vue Multi-word Error

In order to remove the multi-error warning, we have to add the following code in the vue.config.js file:

const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  lintOnSave: false,
})

 

Step 3- Install & Configure Vuetify Plugin

Creating a user-friendly application is a challenge in the real world. Vuetify is a powerful Vue UI library with beautifully handcrafted Material Design UI components. Vuetify offers complete support for Vue and comes with cleaner, semantic and reusable UI components.

We will use the below command to install the Vuetify plugin in Vue:

npm install vuetify

Here, we will enable the Vuetify package globally in Vue by adding the below 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')

 

Further, we will open the 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">

 

Step 4- Vuetify Simple Table Example In Vue

The v-simple-table directive creates the table component in Vue. It needs to be placed inside our 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 the FOOD array and displaying the data with the table component:

Vuetify Simple Table Example in Vue

 

Step 5- Fixed Header Table Example

We should add the fixed-header property along with the height property in the 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>

 

Step 6- Table Dark Theme

Update the table’s current theme to a dark theme can be done by just adding the dark tag to the 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 a dark theme:

Vue Table Dark theme

 

Step 7- Build Data Tabe In Vue.js

Afterward, we will create Data Table in Vue using the 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>

Vue Custom Table with Filter and Sorting

 

Step 8- TypeError: Cannot Read Property ‘width’ Of Undefined

To get rid of the width undefined Vuetify error, we must define the vuetify library to mounting function in the 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')

 

Step 9- Search DataTable In Vue

We have to add a search prop to enable the filtering feature in Data Tables which is quite 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>

Now, we start the app in the browser:

npm run serve

Search DataTable in Vue

 

Conclusion

Now, we have reached the end of this Vue Table tutorial with various examples. I hope that the steps were not very difficult to understand.

 

Thanks

Leave a Reply

Your email address will not be published. Required fields are marked *