Home > Mobile >  Filter through a Table in Vue
Filter through a Table in Vue

Time:10-05

I'm trying to create a Vue app that renders a number of quotes and allows you to search through the data. I think maybe I'm not binding the function to the right element. I have a v-model attribute on the input tag so that should bind whatever text a user inputs in.

Here's my template:

<template>
  <div class="container">
    <h3>Quotes</h3>
    <div class="controllers">
      <div class="search">
         <input id="search-item" type="text" placeholder="Search for a quote..." v-model="searchText"/>
         <button @click="searchResults()" class="search-btn">Search</button>
      </div>
    </div>
    <table class="table">
      <thead>
        <tr>
          <th scope="col">Source</th>
          <th scope="col">Context</th>
          <th scope="col">Quote</th>
          <th scope="col">Theme</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="quote in quotes" v-bind:key="quote.quote"> 
          <th scope="row">{{quote.context}}</th>
          <td>{{quote.source}}</td>
          <td>{{quote.quote}}</td>
          <td>{{quote.theme}}</td>
        </tr>
      </tbody>
    </table> 
  </div> 
</template>

Here's my script

  import axios from 'axios';
  export default {
    name: 'Quotes',
    data() {
      return {
        searchText: '',
        // search: null,
        // data: null,
        quotes: [ 
          {
            quote: null,
            context:  null,
            source: null,
            theme: null,
            currentPage: 0,
        }
        ],
      };
    },
    mounted() {
      axios
        .get('https://gist.githubusercontent.com/benchprep/dffc3bffa9704626aa8832a3b4de5b27/raw/quotes.json')
        .then(res => {
          this.quotes = res.data;
        })
      },
    methods: {
      searchResults() {
        if (this.searchText.length === 0) {
        return '';
      }
      return this.quotes.filter(quote => quote.quote.match(this.searchText));
     },
  }
}

When I try and implement a search the functionality doesn't work. I'm not getting any errors in the compiler.

CodePudding user response:

The problem is on the searchResults() function because it is only filtering this.quotes and return this value, but this value is not used, thus the object this.quotes continue with the started values. I'd suggest that you update the this.quotes when call the function searchResults() but remember to save the initial results.

The best way for this is to use a computed variable that return this.quotes filtered when needed. See in https://vuejs.org/v2/guide/computed.html#Computed-Properties

CodePudding user response:

Your method is wrong it should be:

    searchResults() {
        if (this.searchText.length == 0 || this.searchText == '') return;
        this.quotes = this.quotes.filter(quote => quote.quote.match(this.searchText));
    }

You dont return this.quotes, you change the array instead. But this will cause to empty the array so instead you should use another variable with the original array.

This is better:

    export default {
        name: 'Quotes',
        data() {
            return {
                searchText: '',
                data: [],
                quotes: [],
            };
        },
        async fetch() {
            this.data = await fetch('https://gist.githubusercontent.com/benchprep/dffc3bffa9704626aa8832a3b4de5b27/raw/quotes.json').then(res => res.json());
            this.quotes = this.data;
        },
        methods: {
            searchResults() {
                if (this.searchText.length == 0 || this.searchText == '') {
                    this.quotes = this.data;
                }
                this.quotes = this.data.filter(quote => quote.quote.toLowerCase().includes(this.searchText.toLowerCase()));
            }
        }
    }

BTW. This is with nuxt, just change the part of fetch to axios.

  • Related