VueJS Sort Object of Objects

by Alen Subasic

HTML

<!doctype html>
<html lang="en">

  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

    <title>Goals</title>
  </head>

  <body>
    <h1>Goals</h1>

    <div id="userList">
      <goal-list :users="users"></goal-list>
    </div>

    <!-- Vue.js -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.js"></script>

    <!-- Custom JavaScript -->
    <script src="/script.js"></script>"
  </body>

</html>

JavaScript

const userGoals = {
  "Alen": {
    order: 1,
    goals: ["Learn JavaScript.", "Learn VueJS.", "Learn React."]
  },
  "Lucas": {
    order: 2,
    goals: ["Learn to draw.", "Build a canoe.", "Paint a painting."]
  },
  "Cole": {
    order: 3,
    goals: ["Learn JavaScript.", "Learn to paint.", "Learn Karate."]
  },
  "Tahir": {
    order: 0,
    goals: ["Lift something heavy.", "Lift something even heavier!", "Relax."]
  }
}

Vue.component('goal-list', {
  props: {
    users: Object
  },
  template: `
	<div>
		<ol v-for="(user, index) in sortedUsers">
			<strong>Order:</strong> {{ user.order }} <strong>Name:</strong> {{ user.key }}
			<li v-for="goal in user.goals"> {{ goal }}</li>
		</ol>
	</div>
	`,
  computed: {
    sortedUsers() {
      return Object.keys(this.users)
        .map(i => {
          this.$set(this.users[i], 'key', i)
          return this.users[i]
        }).sort((a, b) => {
          return a.order > b.order ? 1 : (a.order < b.order ? -1 : 0)
        });
    }
  }
});

var list = new Vue({
  el: '#userList',
  data() {
    return {
      users: userGoals
    }
  }
});