1

I'm learning Vue JS and trying to use multiple filters to filter multiple products.

So, I have an example of 6 filters, product 1 to product 6. And I also have 6 products with different categories. I've coded as below, but when I try to click button filter, to filter the product, it doesn't work. I've tried various ways still not working.

Can anyone help me explain it and deal with this problem?

new Vue({
  el: '#app',

  data () {
    return {
      categories:[
        {
          category_title: 'Product 1',
          category_name: "product-1"
        },
        {
          category_title: 'Product 2',
          category_name: "product-2"
        },
        {
          category_title: 'Product 3',
          category_name: "product-3"
        },
        {
          category_title: 'Product 4',
          category_name: "product-4"
        },
        {
          category_title: 'Product 5',
          category_name: "product-5"
        },
        {
          category_title: 'Product 6',
          category_name: "product-6"
        },
      ],
      productItems: [
        {
          name: 'Pro1',
          category: 'product-1'
        },
        {
          name: 'Pro2',
          category: 'product-2'
        },
        {
          name: 'Pro3',
          category: 'product-3'
        },
        {
          name: 'Pro4',
          category: 'product-4'
        },
        {
          name: 'Pro5',
          category: 'product-5'
        },
        {
          name: 'Pro6',
          category: 'product-6'
        },
      ],
    }
  },
  computed: {
    productFilter(){
      return this.productItems;
    },
    filterProduct(){
      return this.productItems.filter((product) => product.category == this.categories.category_name)
    }
  }
})
.product-items span{
  margin: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" integrity="sha512-iBBXm8fW90+nuLcSKlbmrPcLa0OT92xO1BIsZ+ywDWZCvqsWgccV3gFoRBv0z+8dLJgyAHIhR35VZc2oM/gI1w==" crossorigin="anonymous" referrerpolicy="no-referrer" />

<div id="app">
  <div class="product-filter">
    <button @click="filterProduct" v-for="cat in categories" :key="cat.id">
      {{ cat.category_title }}
    </button>
  </div>
  
  <div class="product-items">
    <span v-for="product in productFilter" :key="product.id">{{ product.name }}</span>
  </div>
</div>

2 Answers 2

3

Move the filterProduct from the computed properties to methods. Generally actions are to be placed inside methods and the computed properties holds the data which changes with respect to the dependent values used inside the defenition of that particular computed property.

Here I have created a data property called activeCategory which is being set when the user clicks any one of the category button. The productFilter computed property makes use of activeCategory data property. So when ever the data property activeCategory gets updated from the function filterProduct, the productFilter computed property automatically retrns new set of products.

new Vue({
  el: '#app',

  data() {
    return {
      categories: [
        {
          category_title: 'Product 1',
          category_name: "product-1"
        },
        {
          category_title: 'Product 2',
          category_name: "product-2"
        },
        {
          category_title: 'Product 3',
          category_name: "product-3"
        },
        {
          category_title: 'Product 4',
          category_name: "product-4"
        },
        {
          category_title: 'Product 5',
          category_name: "product-5"
        },
        {
          category_title: 'Product 6',
          category_name: "product-6"
        },
      ],
      productItems: [
        {
          name: 'Pro1',
          category: 'product-1'
        },
        {
          name: 'Pro2',
          category: 'product-2'
        },
        {
          name: 'Pro3',
          category: 'product-3'
        },
        {
          name: 'Pro4',
          category: 'product-4'
        },
        {
          name: 'Pro5',
          category: 'product-5'
        },
        {
          name: 'Pro6',
          category: 'product-6'
        },
      ],
      activeCategory: null,
    }
  },
  methods: {
    filterProduct(category) {
      this.activeCategory = category;
    }
  },
  computed: {
    productFilter() {
      return this.activeCategory ?
        this.productItems.filter((product) => product.category == this.activeCategory.category_name) :
        this.productItems;
    },
  }
})
.product-items span {
  margin: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css"
  integrity="sha512-iBBXm8fW90+nuLcSKlbmrPcLa0OT92xO1BIsZ+ywDWZCvqsWgccV3gFoRBv0z+8dLJgyAHIhR35VZc2oM/gI1w=="
  crossorigin="anonymous" referrerpolicy="no-referrer" />
<div id="app">
  <div class="product-filter">
    <button @click="filterProduct(cat)" v-for="cat in categories" :key="cat.id">
      {{ cat.category_title }}
    </button>
  </div>

  <div class="product-items">
    <span v-for="product in productFilter" :key="product.id">{{ product.name }}</span>
  </div>
</div>

Sign up to request clarification or add additional context in comments.

1 Comment

ah thank you, i got it. Thank you so much for your explanation
2

The method filterProduct should be defined inside methods option and add filtered property that will take the filtered products when you click the button, this click button runs the method that takes the current category as parameter :

new Vue({
  el: '#app',

  data() {
    return {
      categories: [{
          category_title: 'Product 1',
          category_name: "product-1"
        },
        {
          category_title: 'Product 2',
          category_name: "product-2"
        },
        {
          category_title: 'Product 3',
          category_name: "product-3"
        },
        {
          category_title: 'Product 4',
          category_name: "product-4"
        },
        {
          category_title: 'Product 5',
          category_name: "product-5"
        },
        {
          category_title: 'Product 6',
          category_name: "product-6"
        },
      ],
      productItems: [{
          name: 'Pro1',
          category: 'product-1'
        },
        {
          name: 'Pro2',
          category: 'product-2'
        },
        {
          name: 'Pro3',
          category: 'product-3'
        },
        {
          name: 'Pro4',
          category: 'product-4'
        },
        {
          name: 'Pro5',
          category: 'product-5'
        },
        {
          name: 'Pro6',
          category: 'product-6'
        },
      ],
      filtered: []
    }
  },
  computed: {
    productFilter() {
      return this.productItems;
    },

  },
  methods: {
    filterProduct(cat) {
      this.filtered = this.productItems.filter((product) => product.category == cat.category_name)
    }
  }
})
.product-items span {
  margin: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" integrity="sha512-iBBXm8fW90+nuLcSKlbmrPcLa0OT92xO1BIsZ+ywDWZCvqsWgccV3gFoRBv0z+8dLJgyAHIhR35VZc2oM/gI1w==" crossorigin="anonymous" referrerpolicy="no-referrer"
/>

<div id="app">
  <div class="product-filter">
    <button @click="filterProduct(cat)" v-for="cat in categories" :key="cat.id">
      {{ cat.category_title }}
    </button>
  </div>

  <div class="product-items">
    <span v-for="product in filtered" :key="product.id">{{ product.name }}</span>
  </div>
  <pre>

<pre>
{{filtered}}
</pre>
</div>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.