Search code examples
arraysvue.jsv-forcomputed-properties

Change Computed Property on Click


Is it possible to add/change the computed property inside the "v-for" with a click event? I would like to be able to display the list of food based on their category when I click on the proper button.

If I click on the "fruit" button it will be

 <div v-for="food in fruitCategory" :key="food.name" class="card">
      <p>{{ food.name }}</p>
    </div>

and "candy" button it would be

 <div v-for="food in candyCategory" :key="food.name" class="card">
      <p>{{ food.name }}</p>
    </div>

Is this a good approach?

Actual code below

<template>
  <div class="layout">
    <button>all</button>
    <button>fruit</button>
    <button>candy</button>
    <div v-for="food in foods" :key="food.name" class="card">
      <p>{{ food.name }}</p>
    </div>
  </div>
</template>
export default {
  name: 'Food',
  data() {
    return {
      foods: [
        { name: 'banana', category: 'fruit' },
        { name: 'orange', category: 'fruit' },
        { name: 'strawberry', category: 'fruit' },
        { name: 'gum', category: 'candy' },
        { name: 'fuzzy peach', category: 'candy' },
      ]
    }
  },
  computed: {
    fruitCategory: function() {
      return this.foods.filter(function(food) {
        return food.category === 'fruit'
      })
    }
  },
  candyCategory: function() {
    return this.foods.filter(function(food) {
      return food.category === 'candy'
    })
  }
}

Solution

  • You just need to store the category in data and then you can use the filter dynamically.

    here as a working example with a cat array that checks if the category is included.

    new Vue({
      el: "#app",
      name: 'Food',
      data() {
        return {
          cat: ['fruit','candy'],
          foods: [
            { name: 'banana', category: 'fruit' },
            { name: 'orange', category: 'fruit' },
            { name: 'strawberry', category: 'fruit' },
            { name: 'gum', category: 'candy' },
            { name: 'fuzzy peach', category: 'candy' },
          ]
        }
      },
      computed: {
        filtered: function() {
          var cat = this.cat;
          return this.foods.filter(function(food) {
            return cat.indexOf(food.category) >= 0;
          })
        }
      },
    })
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
    
    
    <div id="app">
      <div class="layout">
        <button @click="cat=['fruit', 'candy']">all</button>
        <button @click="cat=['fruit']">fruit</button>
        <button @click="cat=['candy']">candy</button>
        <div v-for="food in filtered" :key="food.name" class="card">
          <p>{{ food.name }}</p>
        </div>
      </div>
    </div>