How to paginate a table in Vue

Implementing pagination in data tables is essential for Vue applications that display large datasets efficiently without overwhelming the interface. As the creator of CoreUI with over 11 years of Vue development experience since 2014, I’ve built paginated tables in countless enterprise dashboards. The most effective solution is to track the current page in state and compute the visible rows based on page size. This approach provides smooth pagination with full control over navigation and display logic.

Use computed properties to paginate table data in Vue 3.

<template>
  <div>
    <table>
      <thead>
        <tr>
          <th>ID</th>
          <th>Name</th>
          <th>Email</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for='item in paginatedData' :key='item.id'>
          <td>{{ item.id }}</td>
          <td>{{ item.name }}</td>
          <td>{{ item.email }}</td>
        </tr>
      </tbody>
    </table>

    <div class='pagination'>
      <button @click='prevPage' :disabled='currentPage === 1'>Previous</button>
      <span>Page {{ currentPage }} of {{ totalPages }}</span>
      <button @click='nextPage' :disabled='currentPage === totalPages'>Next</button>
    </div>
  </div>
</template>

<script>
import { ref, computed } from 'vue'

export default {
  setup() {
    const currentPage = ref(1)
    const itemsPerPage = 10

    const data = ref(Array.from({ length: 95 }, (_, i) => ({
      id: i + 1,
      name: `User ${i + 1}`,
      email: `user${i + 1}@example.com`
    })))

    const totalPages = computed(() =>
      Math.ceil(data.value.length / itemsPerPage)
    )

    const paginatedData = computed(() => {
      const start = (currentPage.value - 1) * itemsPerPage
      const end = start + itemsPerPage
      return data.value.slice(start, end)
    })

    const prevPage = () => {
      if (currentPage.value > 1) currentPage.value--
    }

    const nextPage = () => {
      if (currentPage.value < totalPages.value) currentPage.value++
    }

    return { currentPage, totalPages, paginatedData, prevPage, nextPage }
  }
}
</script>

The current page is tracked in a ref, starting at 1. A computed property calculates the total pages based on data length and items per page. Another computed property slices the data array to show only items for the current page. Navigation buttons update the page number with bounds checking to prevent invalid pages.

Best Practice Note

This is the same pagination pattern we use in CoreUI Vue tables for optimal performance. For large datasets, implement server-side pagination by fetching only the required page from your API. Add features like page size selection or jump-to-page input for enhanced navigation.


Speed up your responsive apps and websites with fully-featured, ready-to-use open-source admin panel templates—free to use and built for efficiency.


About the Author