Home » vue » Filtering through a table as user types to input bar

Filtering through a table as user types to input bar

Posted by: admin November 26, 2021 Leave a comment

Questions:

I have a table that is populated based on an array of country objects and I also have a search bar which will interact with the table by live filtering through the countries array and only showing the countries that partially or fully matches what the user inputs in the search bar.

The problem is I am new to vue and I am having trouble figuring out how to get this to work. If someone can look at my code and point me towards the right directly or what I am doing wrong that would be great!

So right now my logic is that I have a v-model on the text field which will bind whatever the user types to a data value called “filterBy”.

My understanding is probably incorrect, but what I am thinking now is that by creating a filteredCountries function inside computed, and since computed will run whenever a variable inside the function changes, it will automatically get called whenever something is typed inside the searchbar, thus filtering the countries array and the table will get rerendered.

<template>
  <div class="countries-table">
    <div class="countries-search-bar">
      <v-flex xs12 sm6 md3>
        <v-text-field
          v-model="filterBy"
          placeholder="Search by country name or alpha2"
        />
      </v-flex>
    </div>
    <v-data-table
      :headers="headerValues"
      :items="items"
      :pagination.sync="pagination"
      item-key="id"
      class="elevation-1"
      :rows-per-page-items="[300]"
    >
      <template v-slot:headers="props">
        <tr>
          <th
            v-for="header in props.headers"
            :key="header.text"
            :class="[
              'column sortable',
              pagination.descending ? 'desc' : 'asc',
              header.value === pagination.sortBy ? 'active' : ''
            ]"
            @click="changeSort(header.value)"
          >
            <v-icon small>arrow_upward</v-icon>
            {{ header.text }}
          </th>
          <th>
            Edit
          </th>
        </tr>
      </template>

      <template v-slot:items="props">
        <tr :active="props.selected" @click="props.selected = !props.selected">
          <td>{{ props.item.country_alpha2 }}</td>
          <td class="text-xs-right">{{ props.item.country_name }}</td>
          <boolean-cell
            custom-class="text-xs-right"
            :input="props.item.is_active"
            :output="{ true: 'Yes', false: 'No' }"
          ></boolean-cell>
          <date-cell
            custom-class="text-xs-right"
            :input="props.item.updated_at"
          ></date-cell>
          <td class="text-xs-right" @click="triggerEdit(props.item)">
            <v-icon class="edit-icon">edit</v-icon>
          </td>
        </tr>
      </template>
    </v-data-table>
  </div>
</template>

<script>
import BooleanCell from '~/components/global-components/Table/BooleanCell'
import DateCell from '~/components/global-components/Table/DateCell'

export default {
  components: {
    BooleanCell,
    DateCell
  },
  props: {
    headerValues: {
      type: Array,
      required: true
    },
    items: {
      type: Array,
      required: true
    }
  },
  computed: {
    filteredCountries() {
      return this.items.filter(country => {
        return country.country_name.includes(this.filterBy)
      })
    }
  },
  data() {
    return {
      pagination: {
        sortBy: 'country_alpha2'
      },
      filterBy: ''
    }
  },
  methods: {
    changeSort(headerValue) {
      if (this.pagination.sortBy === headerValue) {
        this.pagination.descending = !this.pagination.descending
      } else {
        this.pagination.sortBy = headerValue
        this.pagination.descending = false
      }
    }
  }
}
</script>

The table stays the same with the current code I have despite me typing things inside the search bar.

Can someone show me the what I am doing wrong?

Answers:

For the v-data-table items you are using items which is coming as a prop. You should use filteredCountries computed property.