Build Dynamic Data Table in Vue.js 2|3 with Vuetify

Last updated on by Digamber
In this tutorial, we are going to learn how to build a customizable and pageable data table in Vue application using the Vuetify plugin. We will also look at how to add data sorting and filtering feature very easily in Vue.js 2+.

Dynamic Data Table

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

Start the app in the browser.

npm run serve

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

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

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>

Search DataTable in Vue

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.