Build Dynamic Data Table in Vue.js 2+ with Vuetify

  452 views   2 months ago VueJs

In this tutorial, we are going to learn how to build a customizable and pageable data table in Vue application utilizing the Vuetify plugin. We will withal optically canvass how to integrate data sorting and filtering feature very facilely in Vue.js 2+.
What is Data Table?
A table is a relegation of data in rows and columns, or probably in a more perplexed structure. Tables are extensively utilized for data analysis, communication, and research and can be utilized in sundry 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 utilizer can expeditiously scan the exhibited 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.

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>

i hope you like this article.

Author : Harsukh Makwana
Harsukh Makwana

Hi, My name is Harsukh Makwana. i have been work with many programming language like php, python, javascript, node, react, anguler, etc.. since last 5 year. if you have any issue or want me hire then contact me on harsukh21@gmail.com

Related Articles