Group products by vuejs categories

Asked

Viewed 173 times

0

I have a component that displays products and I have an H2 where I display the category name. The problem is that the names of the repeated categories appear, since two products belong to the same category. I would like to display the title "Category 1" and after that the products, without repeating the "Category 1" again for product 2.

Array Categories:

{
    id: 1,
    name: Categoria 1,
}

Array Products:

  {
     id: 10
     name: Produto 1,
     category_id: 1
  },
  {
     id: 11,
     name: Produto 2,
     category_id: 1
  }

Component:

<template>
<div>
    <div v-for="product in products" :key="product.id">
        <h2 class="text-danger font-weight-bold mt-3" v-for="category in categories" :key="category.id" :value="category.id" v-if="category.id === product.category_id">{{ category.name }}</h2>
        <div class="row">
            <div class="col-12 col-md-4">
                <div class="card mb-3">
                    <a href="" data-toggle="modal" data-target="#product-modal">
                        <div class="card-body">
                            <h3 class="text-danger font-weight-bold">{{ product.name }}</h3>
                        </div>
                    </a>
                </div>
            </div>
        </div>
    </div>
</div>
</template>

<script>
export default {
    name: "CategoryProduct",
    data() {
        return {
            categories: [],
            products: []
        }
    },
    methods: {
        getCategories() {
            axios
                .get('/api/categories')
                .then(response => {
                    this.categories = response.data;
                })
                .catch(error => console.log(error));
        },
        getProducts() {
            axios
                .get('/api/products')
                .then(response => {
                    this.products = response.data;
                })
                .catch(error => console.log(error));
        }
    },
    mounted() {
        this.getCategories();
        this.getProducts();
    }
}
</script>
  • Give an example of what the objects inside are like categories, you want to group them by category.name? - It is preferable to create an example only with the code needed to reproduce the problem, your question has excess code. - [Ask]

  • I reduced the code and put the example. I want to group by the category name.

1 answer

3


Categories are repeating as you are using the first v-for with the products, instead of using the product variable.

What you need to do is scroll through the categories as this, you filter the products through the fields product.categoryId and category.id. In my example, I did a function filterProducts to perform the above task.

In this way, instead of using products in products, we will use products in filterProducts(category.id).

const app = new Vue({
  el: '#app',
  data: () => {
    return {
      categories: [{
        id: 1,
        name: 'Categoria #1'
      }, {
        id: 2,
        name: 'Categoria #2'
      }],
      products: [{
        id: 10,
        name: 'Produto 1',
        categoryId: 1
      }, {
        id: 20,
        name: 'Produto 2',
        categoryId: 1
      }, {
        id: 30,
        name: 'Produto 3',
        categoryId: 2
      }]
    }
  },
  methods: {
    /**
     * Filtra os produtos conforme o ID da categoria
     * @params {Number}
     * @returns {Array}
     */
    filterProducts(categoryId) {
      return this.products.filter(p => p.categoryId === categoryId)
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  <ul>
    <li v-for="category in categories">
      {{ category.name }}
      <ul>
        <li v-for="product in filterProducts(category.id)">
          {{ product.name }}
        </li>
      </ul>
    </li>
  </ul>
</div>

There is also another way to do this, just use the v-if to "filter" the products. Below is an example.

const app = new Vue({
  el: '#app',
  data: () => {
    return {
      categories: [{
        id: 1,
        name: 'Categoria #1'
      }, {
        id: 2,
        name: 'Categoria #2'
      }],
      products: [{
        id: 10,
        name: 'Produto 1',
        categoryId: 1
      }, {
        id: 20,
        name: 'Produto 2',
        categoryId: 1
      }, {
        id: 30,
        name: 'Produto 3',
        categoryId: 2
      }]
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  <ul>
    <li v-for="category in categories">
      {{ category.name }}
      <ul>
        <li
          v-for="product in products"
          v-if="product.categoryId == category.id"
        >
          {{ product.name }}
        </li>
      </ul>
    </li>
  </ul>
</div>

Browser other questions tagged

You are not signed in. Login or sign up in order to post.