How to filter a table in Vue

Implementing table filtering allows users to narrow down data based on search terms and criteria, essential for data-heavy Vue applications. As the creator of CoreUI with over 11 years of Vue development experience since 2014, I’ve built advanced filtering systems in countless enterprise tables. The most effective solution is to use reactive state for filter criteria and computed properties to apply filtering logic. This approach provides real-time, efficient filtering with support for multiple conditions.

Use computed properties to filter table data in Vue 3.

<template>
  <div>
    <div class='filters'>
      <input
        v-model='searchTerm'
        type='text'
        placeholder='Search by name or email...'
      />

      <select v-model='statusFilter'>
        <option value=''>All Status</option>
        <option value='active'>Active</option>
        <option value='inactive'>Inactive</option>
      </select>

      <input
        v-model.number='minAge'
        type='number'
        placeholder='Min age'
      />
    </div>

    <table>
      <thead>
        <tr>
          <th>Name</th>
          <th>Email</th>
          <th>Age</th>
          <th>Status</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for='item in filteredData' :key='item.id'>
          <td>{{ item.name }}</td>
          <td>{{ item.email }}</td>
          <td>{{ item.age }}</td>
          <td>{{ item.status }}</td>
        </tr>
      </tbody>
    </table>

    <p>Showing {{ filteredData.length }} of {{ data.length }} items</p>
  </div>
</template>

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

export default {
  setup() {
    const searchTerm = ref('')
    const statusFilter = ref('')
    const minAge = ref(0)

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

    const filteredData = computed(() => {
      return data.value.filter(item => {
        const matchesSearch = !searchTerm.value ||
          item.name.toLowerCase().includes(searchTerm.value.toLowerCase()) ||
          item.email.toLowerCase().includes(searchTerm.value.toLowerCase())

        const matchesStatus = !statusFilter.value || item.status === statusFilter.value
        const matchesAge = item.age >= minAge.value

        return matchesSearch && matchesStatus && matchesAge
      })
    })

    return { searchTerm, statusFilter, minAge, data, filteredData }
  }
}
</script>

The filter inputs are bound to reactive refs using v-model. A computed property filters the data array based on all active criteria using AND logic. Each filter condition checks if the filter is set before applying it, allowing optional filtering. The search term filters across multiple fields using the includes method with case-insensitive matching.

Best Practice Note

This is the same filtering implementation we use in CoreUI Vue tables for flexible data filtering. For better performance with large datasets, consider debouncing the search input or implementing server-side filtering. Add a clear filters button to reset all criteria simultaneously for improved user experience.


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

Subscribe to our newsletter
Get early information about new products, product updates and blog posts.

Answers by CoreUI Core Team