How to create a reporting app with Vue 3 and Composition API?

Vue 3 with Composition API provides a powerful way to build reporting applications. This tutorial demonstrates creating a data-driven report table that fetches information from an external API and displays it in a structured format.

What is a Reporting App?

A reporting app displays data in organized formats like tables, charts, or dashboards. It transforms raw data into meaningful insights for users to analyze business metrics, user statistics, or any structured information.

Composition API Benefits

The Composition API allows logic-based component organization instead of lifecycle-based structure. This approach creates more maintainable, reusable, and testable code by grouping related functionality together.

Project Setup

First, create a new Vue 3 application with the required dependencies:

npm install -g @vue/cli
npx vue create reporting-app
cd reporting-app
npm install axios vue-router

Router Configuration

Create router.js in the src directory to handle navigation:

import { createRouter, createWebHistory } from 'vue-router'
import HomeView from './views/HomeView.vue'
import ReportTable from './views/ReportTable.vue'

const routes = [
  {
    path: '/',
    name: 'home',
    component: HomeView
  },
  {
    path: '/report',
    name: 'report', 
    component: ReportTable
  }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

export default router

Main Application Setup

Configure the main application in main.js:

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'

const app = createApp(App)
app.use(router)
app.mount('#app')

Update App.vue to handle routing:

<template>
  <div id="app">
    <nav>
      <router-link to="/">Home</router-link> | 
      <router-link to="/report">Report</router-link>
    </nav>
    <router-view />
  </div>
</template>

<script>
export default {
  name: "App"
}
</script>

Creating the Home Component

Create views/HomeView.vue for the home page:

<template>
  <div class="home">
    <h1>Reporting Dashboard</h1>
    <p>Welcome to the Vue 3 reporting application</p>
    <router-link to="/report" class="report-link">View Reports</router-link>
  </div>
</template>

<script>
export default {
  name: 'HomeView'
}
</script>

<style scoped>
.home {
  text-align: center;
  padding: 40px;
}
.report-link {
  display: inline-block;
  padding: 12px 24px;
  background-color: #42b883;
  color: white;
  text-decoration: none;
  border-radius: 4px;
  margin-top: 20px;
}
</style>

Building the Report Table Component

Create views/ReportTable.vue with Composition API for data fetching and display:

<template>
  <div class="report">
    <h1 class="report-heading">Posts Report</h1>
    
    <div v-if="state.loading" class="loading">Loading reports...</div>
    
    <div v-else-if="state.error" class="error">
      Error loading data: {{ state.error }}
    </div>
    
    <table v-else class="report-table">
      <thead>
        <tr>
          <th>User ID</th>
          <th>ID</th>
          <th>Title</th>
          <th>Body</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="report in state.reports" :key="report.id">
          <td>{{ report.userId }}</td>
          <td>{{ report.id }}</td>
          <td>{{ report.title }}</td>
          <td>{{ report.body }}</td>
        </tr>
      </tbody>
    </table>
    
    <div v-if="state.reports.length" class="report-summary">
      Total Reports: {{ state.reports.length }}
    </div>
  </div>
</template>

<script>
import { reactive, onMounted } from "vue"
import axios from "axios"

export default {
  name: "ReportTable",
  setup() {
    // Reactive state using Composition API
    const state = reactive({
      reports: [],
      loading: false,
      error: null
    })

    // Function to fetch reports
    const fetchReports = async () => {
      state.loading = true
      state.error = null
      
      try {
        const response = await axios.get("https://jsonplaceholder.typicode.com/posts")
        state.reports = response.data
      } catch (error) {
        state.error = error.message
        console.error("Error fetching reports:", error)
      } finally {
        state.loading = false
      }
    }

    // Fetch data when component mounts
    onMounted(() => {
      fetchReports()
    })

    return {
      state,
      fetchReports
    }
  }
}
</script>

<style scoped>
.report {
  max-width: 1200px;
  margin: 0 auto;
  padding: 20px;
  font-family: Arial, sans-serif;
}

.report-heading {
  font-size: 28px;
  color: #2c3e50;
  margin-bottom: 20px;
  text-align: center;
}

.loading, .error {
  text-align: center;
  padding: 20px;
  font-size: 18px;
}

.error {
  color: #e74c3c;
}

.report-table {
  width: 100%;
  border-collapse: collapse;
  margin-bottom: 20px;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

.report-table th {
  background-color: #34495e;
  color: white;
  padding: 12px;
  text-align: left;
  font-weight: bold;
}

.report-table td {
  background-color: #f8f9fa;
  padding: 12px;
  border-bottom: 1px solid #dee2e6;
}

.report-table tr:hover td {
  background-color: #e9ecef;
}

.report-summary {
  text-align: center;
  font-weight: bold;
  color: #2c3e50;
  padding: 10px;
}
</style>

Key Composition API Features Used

  • reactive() - Creates reactive state object that automatically triggers re-renders
  • onMounted() - Lifecycle hook for component mount events
  • setup() - Composition API entry point for component logic

Running the Application

Start the development server:

npm run serve

Navigate to http://localhost:8080/report to view the reporting table with live data from the JSONPlaceholder API.

Conclusion

This Vue 3 reporting app demonstrates the power of Composition API for creating reactive, maintainable applications. The reactive state automatically handles data updates, while the modular setup function keeps logic organized and reusable.

Updated on: 2026-03-15T23:19:01+05:30

803 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements