[Vuejs]-How To Sort Data From An Object In Vue templates?

3👍

Something like this. Here I’m obviously not using Vuex, but you could use a Vuex getter. If you need the id of the topic in the sorted objects, you could add it in your map.

console.clear()

// topics:
//   - [firebase-push-key]
//     - title
//     - text
//     - ...
  
const topics = {
  "1234":{
    title: "Ziss one starts with Z",
    text: "text1"
  },
  "2345":{
    title: "M is for middle",
    text: "text2"
  },
  "3456":{
    title: "Alpha title",
    text: "text3"
  }
}

new Vue({
  el:"#app",
  data:{
    topics
  },
  methods:{
    sortProperty(prop){
      return (a,b) => {
        if (a[prop] < b[prop])
          return -1;
        if (a[prop] > b[prop])
          return 1;
        return 0;       
      }
    }
  },
  computed:{
    sortedTopics(){
      return Object.keys(this.topics)
        .map(t => {
          this.$set(this.topics[t], 'key', t)
          return this.topics[t]
        })
        .sort(this.sortProperty('title'))
    }
  }
})
<script src="https://unpkg.com/vue@2.2.6/dist/vue.js"></script>
<div id="app">
  <div v-for="topic in sortedTopics">
    {{topic}}
  </div>
</div>

Edit

Here is an example that handles your updated data structure.

const topics = [{
  "-Kmbspn0WYBlNXfmfVlR": {
    "slug": "arne",
    "title": "Arne"
  }
}, {
  "-KmbsqiG_9uXzRhHrnXZ": {
    "slug": "tati",
    "title": "Tati"
  }
}, {
  "-KmbsrllgJzV7BA_NeCO": {
    "slug": "abel",
    "title": "Abel"
  }
}]

new Vue({
  el: "#app",
  data: {
    topics
  },
  methods: {
    sortByObjectProperty(prop, getter) {
      return (a, b) => {
        a = getter(a), b = getter(b)
        if (a[prop] < b[prop])
          return -1;
        if (a[prop] > b[prop])
          return 1;
        return 0;
      }
    }
  },
  computed: {
    sortedTopics() {
      const getter = v => v[Object.keys(v)[0]]
      const sorter = this.sortByObjectProperty("title", getter)
      return this.topics.sort(sorter)
    }
  }
})
<script src="https://unpkg.com/vue@2.2.6/dist/vue.js"></script>
<div id="app">
  <div v-for="topic in sortedTopics">
    {{topic}}
  </div>
</div>

In this code (as in the above code), sortByObjectProperty is a sort function generator. You pass it any property name it will generate a sorting function for objects that have that property. In order to handle the data structure you have in your topics I added a getter parameter which is a function you can use to tell the sorter how to get the object it needs to sort.

I was worried initially about the performance of v[Object.keys(v)[0]] but that seems to be addressed, at least my own satisfaction, in the comments here.

If you don’t have to support IE, or you are using something that compiles to javascript that supports it, you could also define a default for the getter parameter in cases where you don’t need to sort by a nested object.

sortByObjectProperty(prop, getter = g => g) {...}

Which you could then use as

const sorter = this.sortByObjectProperty("someProperty")
👤Bert

Leave a comment