How to Build Dynamic Data Table in Vue 2 with Vuetify

Last Updated on by in Vue JS
In this tutorial, we will learn how to build a customizable and data table with pagination in Vue application using the Vuetify plugin.We will also look at how to add data sorting and filtering functionality very easily in Vue component.

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

You can use the following command to install Vuetify plugin in Vue.

npm install vuetify@v2-stable

After the plugin is installed, create the new webpack.config.js file at the root of your project. Also, add the following code to the file.

// webpack.config.js

module.exports = {
    module: {
      rules: [
        {
          test: /\.s(c|a)ss$/,
          use: [
            'vue-style-loader',
            'css-loader',
            {
              loader: 'sass-loader',
              // Requires sass-loader@^7.0.0
              options: {
                implementation: require('sass'),
                indentedSyntax: true // optional
              },
              // Requires >= sass-loader@^8.0.0
              options: {
                implementation: require('sass'),
                sassOptions: {
                  indentedSyntax: true // optional
                },
              },
            },
          ],
        },
      ],
    }
  }

Create a plugin file for Vuetify, inside the src/ folder create plugins/ folder, also create vuetify.js file.

Next, add the given code in the src/plugins/vuetify.js file:

import Vue from 'vue'
import Vuetify from 'vuetify'
import 'vuetify/dist/vuetify.min.css'

Vue.use(Vuetify)

const opts = {}

export default new Vuetify(opts)

Enable the Vuetify package globally in Vue by adding the following code in the main.js.

import Vue from "vue";
import App from "./App.vue";
import vuetify from '@/plugins/vuetify' // path to vuetify export

new Vue({
  vuetify,
  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.

Add below code to the components/HelloWorld.vue file:

<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.

Vuetify Simple Table Example in Vue

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.

Vue Table 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>

Vue Custom Table with Filter and Sorting

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

Search DataTable in Vue

Conclusion

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.