0
votes

I have users data fetched from the server which is sorted in desc order of age. When the users data is passed to the child component, it doesn't display data sorted in the desc order of the age in the v-data-table and when I refresh the page then it shows data sorted in the descending order. Please help me find where I am going wrong. I am using vuetify version 2.3.10

When the data is fetched from the server in the parent component it is as follows:

[{full_name: 'James Ross', city: 'Toronto', age: 45 },{full_name: 'Stacey Purkis', city: 'Calgary', age: 32 }, {full_name: 'Jazz Alzo', city: 'London', age: 24 }]

When the child component loads for the first time the users data is as follows:

[{full_name: 'Stacey Purkis', city: 'Calgary', age: 32 }, {full_name: 'Jazz Alzo', city: 'London', age: 24 }, {full_name: 'James Ross', city: 'Toronto', age: 45 }]

So basically it is not sorted and when I refresh the page then users data in the child component shows perfectly finish

[{full_name: 'James Ross', city: 'Toronto', age: 45 },{full_name: 'Stacey Purkis', city: 'Calgary', age: 32 }, {full_name: 'Jazz Alzo', city: 'London', age: 24 }]

parent component

<template>
  <div>
      <Users :users="users"></Users>
  </div>
</template>


<script>
import Users from 'views/lawyers/_users_table.vue';

export default {
  components: {
    Users
  },
  data: () => ({
    users: [],
  }),
  created: function() {
    this.fetchUsers();
  },
  methods: {
    fetchUsers() {
      this.$axios.get('/users.json')
      .then(response => {
        this.users = response.data;
      })
    }
  }
};
</script>

childcomponent

  <template>
   <div>
    <v-data-table
              :headers="headers"
              :items="users"
              :disable-pagination="true"
              v-model="users"
              hide-default-footer
              class="elevation-1"
     >
       <template slot="item" slot-scope="props">
         <tr>
           <td class="full-name">{{ props.item.full_name }}</td>
           <td class="summary">{{ props.item.address}}</td>
           <td class="experience">{{ props.item.age }} years</td>
         </tr>
       </template>
    </v-data-table>
   </div>
  </template>
   



<script>

export default {
  props: ['users'],
  data: () => ({
    headers: [
      { text: 'Name', value: 'full_name', sortable: false  },
      { text: 'Address', value: 'address', sortable: false  },
      { text: 'Age',value: 'age' }
    ]
  }),
};
</script>
1

1 Answers

2
votes

The best way to keep it safe is to set sort-by in your data-table:

<v-data-table
          :sort-by="['age']"
          :headers="headers"
          :items="users"
          :disable-pagination="true"
          v-model="users"
          hide-default-footer
          class="elevation-1"
 >

[UPDATE]

To complete Václav Procházka's answer, you can also provide sort-desc to force it to be decrescent.

Also It's an anti-pattern since v2 to mutate props directly check docs here. The ideal way is to make a clone of it or to use a computed property like below.

Using this.$emit('update:usersProp', val) will try to update your prop on parent component so you parent should look like this <Users :usersProp.sync="users"></Users> or if you use this.value and this.$emit(input, val), then you can use <Users v-model="users"></Users>. Docs here and here

new Vue({
  el: '#app',
  vuetify: new Vuetify(),
  props: {
    usersProp: {
      default: () => {
        return [
          {full_name: 'Stacey Purkis', city: 'Calgary', age: 32 },
          {full_name: 'Jazz Alzo', city: 'London', age: 24 },
          {full_name: 'James Ross', city: 'Toronto', age: 45 }
        ]
      }
    }
  },
  data: () => ({
    headers: [
      { text: 'Name', value: 'full_name', sortable: false  },
      { text: 'Address', value: 'address', sortable: false  },
      { text: 'Age',value: 'age' }
    ],
  }),
  computed: {
    users: {
      get () {
        return this.usersProp
      },
      set (val) {
        this.$emit('update:usersProp', val)
      }
    }
  }
})
<!DOCTYPE html>
<html>
<head>
  <link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
  <link href="https://cdn.jsdelivr.net/npm/@mdi/[email protected]/css/materialdesignicons.min.css" rel="stylesheet">
  <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.css" rel="stylesheet">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
</head>
<body>
  <div id="app">
    <v-app>
      <v-main>
        <v-container>
        <v-data-table
          :headers="headers"
          :items="users"
          :sort-by="['age']"
          :sort-desc="true"
          :disable-pagination="true"
          v-model="users"
          hide-default-footer
          class="elevation-1"
  ></v-data-table>
        </v-container>
      </v-main>
    </v-app>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.js"></script>
</body>
</html>