How to sort a table in Vue

Implementing table sorting allows users to organize data by any column, essential for data-heavy Vue applications and dashboards. As the creator of CoreUI with over 11 years of Vue development experience since 2014, I’ve built sortable tables in countless enterprise applications. The most effective solution is to use reactive state for sort configuration and a computed property to return sorted data. This approach provides efficient, reactive sorting with clear column indicators.

Use reactive state and computed properties for table sorting in Vue 3.

<template>
  <table>
    <thead>
      <tr>
        <th @click='sortBy("id")'>
          ID {{ getSortIcon('id') }}
        </th>
        <th @click='sortBy("name")'>
          Name {{ getSortIcon('name') }}
        </th>
        <th @click='sortBy("age")'>
          Age {{ getSortIcon('age') }}
        </th>
      </tr>
    </thead>
    <tbody>
      <tr v-for='item in sortedData' :key='item.id'>
        <td>{{ item.id }}</td>
        <td>{{ item.name }}</td>
        <td>{{ item.age }}</td>
      </tr>
    </tbody>
  </table>
</template>

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

export default {
  setup() {
    const sortKey = ref('id')
    const sortOrder = ref('asc')

    const data = ref([
      { id: 3, name: 'John Doe', age: 30 },
      { id: 1, name: 'Jane Smith', age: 25 },
      { id: 2, name: 'Bob Johnson', age: 35 }
    ])

    const sortedData = computed(() => {
      return [...data.value].sort((a, b) => {
        let aVal = a[sortKey.value]
        let bVal = b[sortKey.value]

        if (typeof aVal === 'string') {
          aVal = aVal.toLowerCase()
          bVal = bVal.toLowerCase()
        }

        if (aVal < bVal) return sortOrder.value === 'asc' ? -1 : 1
        if (aVal > bVal) return sortOrder.value === 'asc' ? 1 : -1
        return 0
      })
    })

    const sortBy = (key) => {
      if (sortKey.value === key) {
        sortOrder.value = sortOrder.value === 'asc' ? 'desc' : 'asc'
      } else {
        sortKey.value = key
        sortOrder.value = 'asc'
      }
    }

    const getSortIcon = (key) => {
      if (sortKey.value !== key) return ''
      return sortOrder.value === 'asc' ? '↑' : '↓'
    }

    return { sortedData, sortBy, getSortIcon }
  }
}
</script>

The sortKey and sortOrder refs track which column to sort by and the direction. A computed property creates a sorted copy of the data using the array sort method. Clicking a header calls sortBy(), which toggles the direction if clicking the same column or sets ascending order for a new column. The getSortIcon() function displays arrows showing the current sort state.

Best Practice Note

This is the same sorting implementation we use in CoreUI Vue tables for data organization. For case-insensitive string sorting, convert values to lowercase before comparison. For large datasets, consider server-side sorting to reduce client processing and improve performance.


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