Vue.js: v-for over object results in wrong order of keys

Viewed 655

I'm having problems with Vue not respecting the order of keys. The initial data I pass to the vue component as a prop looks like this:

[
  { id: 1, event_name: "event 1", scheduled_at: "2021-01-01" },
  { id: 2, event_name: "event 2", scheduled_at: "2021-01-01" },
  { id: 3, event_name: "event 3", scheduled_at: "2021-01-05" },
  { id: 4, event_name: "event 4", scheduled_at: "2021-01-05" },
  { id: 5, event_name: "event 5", scheduled_at: "2021-01-02" }
]

Then I have a computed prop groupedEvents that groups the events by date (using lodash groupBy). The output is like this:

{
  2021-01-01: [
    { id: 1, event_name: "event 1", scheduled_at: "2021-01-01" },
    { id: 2, event_name: "event 2", scheduled_at: "2021-01-01" },
  ],
  2021-01-02: [
    { id: 5, event_name: "event 5", scheduled_at: "2021-01-02" }
  ],
  2021-01-05: [
    { id: 3, event_name: "event 3", scheduled_at: "2021-01-05" },
    { id: 4, event_name: "event 4", scheduled_at: "2021-01-05" },
  ]
}

The problem: when I do a v-for on groupedEvents, the order of groups is wrong/ignored.

<div v-for="(group, key) in groupedEvents">{{ key }}</div>

The output is

2021-01-01
2021-01-05
2021-01-02

instead of

2021-01-01
2021-01-02
2021-01-05

Ps: ordering function:

let grouped = _.groupBy(this.events, (event) => { return event.scheduled_at })
1 Answers

You can iterate over the sorted keys of the groupedEvents which can also be another computed property with your custom sorting technique:

const childcomponent = Vue.component('childcomponent', {
  template: '#childcomponent',
  props: ['events'],
  computed: {
    groupedEvents() {
      return _.groupBy(this.events, 'scheduled_at');
    }
  }
});

new Vue({
  el:"#app",
  components: { childcomponent },
  data: () => ({
    events: [
      {id: 1, event_name: "event 1", scheduled_at: "2021-01-01"},
      {id: 2, event_name: "event 2", scheduled_at: "2021-01-01"},
      {id: 3, event_name: "event 3", scheduled_at: "2021-01-05"},
      {id: 4, event_name: "event 4", scheduled_at: "2021-01-05"},
      {id: 5, event_name: "event 5", scheduled_at: "2021-01-02"}
    ]
  })
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js" integrity="sha512-90vH1Z83AJY9DmlWa8WkjkV79yfS2n2Oxhsi2dZbIv0nC4E6m5AbH8Nh156kkM7JePmqD6tcZsfad1ueoaovww==" crossorigin="anonymous"></script>

<template id="childcomponent">
  <ul>
    <li v-for="key in Object.keys(groupedEvents).sort()">
      {{ key }}: {{ groupedEvents[key] }}
    </li>
  </ul>
</template>

<div id="app"><childcomponent :events="events"/></div>

Related