WoJ
WoJ

Reputation: 30035

How to v-for iterate in a specific order?

I have and Array of Objects whose elements are randomly ordered. I would like to list the values in a specific order (of the keys).

As an example, the iteration below just lists them:

var vm = new Vue({
  el: "#root",
  data: {
    all: [{
        second: 2,
        third: 3,
        first: 1
      },
      {
        third: 30,
        first: 10,
        second: 20
      }
    ],
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.3/vue.js"></script>
<div id="root">
  <div v-for="a in all">
    <div v-for="(v, k) in a">{{v}}</div>
  </div>
</div>

Is this possible to drive the iteration so that it is ordered according to a list of keys (["first", "second", third"]) which would yield

1
2
3
10
20
30

Upvotes: 6

Views: 12377

Answers (4)

Chad Campbell
Chad Campbell

Reputation: 937

In Module 5 of my Vue.js Training course, I actually discuss this. At first glance, the Object.keys approach may seem like the correct approach. However, different JavaScript engines return the properties in different orders. For that reason, you can't rely on it.

In Vue.js, you could either a) sort your Array when the Array gets populated b) Create a "computed property" or c) Create a sort method that you can pass your property into.

In my opinion, you should use option b. The reason why is because computed properties get cached. By doing this, you'll only run your sort code once. However, if you were to use option c the sort would execute during each iteration. Option a is a possibility, but I don't know enough about your scenario to know if this is a real option or not.

Upvotes: 0

sabithpocker
sabithpocker

Reputation: 15566

I don't know vue but you can do it like this in javascript.

<div v-for="k in Object.keys(a).sort()">{{k}}:{{a[k]}}</div>

Also note that alphabetic sorting accidentally fits into your need, but you might need a custom sort function like sort((a,b)=>order.indexOf(a)-order.indexOf(b)) with your custom order order: ["first","second","third","fourth"] which may not be alphabetic.

var vm = new Vue({
  el: "#root",
  data: {
    all: [{
        second: 2,
        third: 3,
        first: 1,
        fourth: 4
      },
      {
        third: 30,
        first: 10,
        second: 20,
        fourth: 40
      }
    ],
    order: ["first","second","third","fourth"]
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.3/vue.js"></script>
<div id="root">
  <div v-for="a in all">
    <div v-for="k in Object.keys(a).sort((a,b)=>order.indexOf(a)-order.indexOf(b))">{{k}}:{{a[k]}}</div>
    <hr/>
  </div>
</div>

Upvotes: 11

Daniel Beck
Daniel Beck

Reputation: 21505

You can put your list of sorted keys in an array and v-for over that instead.

<div v-for="a in all">
  <div v-for="key in presortedListOfKeys">
    {{a[key]}}
  </div>
</div>

Upvotes: 4

Emeke Ajeh
Emeke Ajeh

Reputation: 1030

You can use computed properties and get the all sorted first before iteration through them.

Upvotes: 1

Related Questions