Hans Felix Ramos
Hans Felix Ramos

Reputation: 4424

How to show grouped items using v-for in Vue?

I have an array like this:

// ...
data():{
    return{
        list: [
            { letter: "A", name: "Albert" },
            { letter: "A", name: "Archer" },
            { letter: "B", name: "Blade" },
            { letter: "B", name: "Birdie" },
        ]
    }
}

and I want to display it grouped:

<template>
    <section>
        <div>A:</div>
        <div>Albert</div>
        <div>Archer</div>
    </section>
    <section>
        <div>B:</div>
        <div>Blade</div>
        <div>Birdie</div>
    </section>
</template>

As you can see, I want to append <section> <div>{{letter}}:</div> on the first iteration or if letter is not the same that before, and </section> if it is the last.

One option is to create a computed grouped, but this data is got by an API, and the next letters is getting on scroll. So is it posible to have that result with a v-for?

Upvotes: 0

Views: 1297

Answers (2)

Sphinx
Sphinx

Reputation: 10729

Uses one computed property is one solution.

Once gets new data from the API, uses Array.concat or ... operator to merge into current data property.

Then in computed property, uses one Array.reduce to get the expected output.

new Vue({
  el: '#app',
  data () {
    return {
      items: []
    }
  },
  computed: {
    computedItems: function () {
      return this.items.reduce((pre, cur) => {
        if (!(cur.letter in pre)) pre[cur.letter] = []
        pre[cur.letter].push(cur)
        return pre
      }, {})
    }
  },
  methods: {
    getItemsFromAPI: function () {
      setTimeout(() => {
        this.items = [...this.items, ...[
            { letter: "A", name: "Albert" },
            { letter: "A", name: "Archer" },
            { letter: "B", name: "Blade" },
            { letter: "B", name: "Birdie" },
        ]]
      }, 1000)
    },
    getItemsFromAPI1: function () {
      setTimeout(() => {
        this.items = [...this.items, ...[
            { letter: "C", name: "Albert" },
            { letter: "C", name: "Archer" },
            { letter: "D", name: "Blade" },
            { letter: "D", name: "Birdie" },
        ]]
      }, 1000)
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
    <button @click="getItemsFromAPI()">Load Data</button>
    <button @click="getItemsFromAPI1()">Load Data (new letter)</button>
    <section v-for="(group, key) in computedItems" :key="key">
        <div>{{key}}</div>
        <div v-for="(item, index) in group" :key="index">
        {{index}}: {{item.name}}
        </div>
    </section>
</div>

Upvotes: 2

Kevin Li
Kevin Li

Reputation: 150

I am not sure that I understand you exactly but I think you want this.

<div v-for="item in list">
      <div v-for="person in Object.keys(item)">{{item[person]}}</div>
</div>

Upvotes: 1

Related Questions