Using method with v-data-table sort button?

1k Views Asked by At

enter image description here

I would like to use the built-in short button not just to sort the items but also to call one of my own methods. Is there any solution to this?

2

There are 2 best solutions below

0
On

Let's give that a try...

For your <v-data-table, add :options.sync="options"

    <v-data-table
      :options.sync="options"

Declare options as options: {}, within your data block

  data: () => ({
    options: {},

Now do what you need to do in watch like

  watch: {
    options: {
      immediate: true,
      deep: true,
      handler() {
        if (Object.keys(this.options).length !== 0) {
          if (this.options.sortBy?.length ?? 0 > 0) {
            if (this.options.sortBy[0]) {
              this.sort = this.options.sortBy[0];
              if (this.options.sortDesc[0]) this.sort = this.sort + ":desc";
            } else {
              this.sort = "";
            }
          }
          this.loadAccounts();
        }
      },
    },
  },

Your this.loadAccounts() could look like

  methods: {
    ...mapActions("accounts", ["getAccounts"]),
    loadAccounts() {
      let params = {
        page: this.options.page,
        limit: this.options.itemsPerPageOptions,
        sort: this.options.sort,
      };
      this.getAccounts(params);
    },
  },
0
On

You can use :custom-sort directive inside <v-data-table> to achieve the requirement you have.

Working Demo :

new Vue({
    el: '#app',
    data() {
        return {
            food: [
                { name: 'Frozen Yogurt', calories: 159, fat: 6, carbs: 24 },
                { name: 'Ice cream sandwich', calories: 237, fat: 9, carbs: 37 }
            ],
            headers: [
                { text: 'Dessert (100g serving)', align: 'left', value: 'name' },
                { text: 'Calories', align: 'left', value: 'calories' },
                { text: 'Fat (g)', align: 'left', value: 'fat' },
                { text: 'Carbs (g)', align: 'left', value: 'carbs' }
            ],
            search: '',

        };
    },
    methods: {
        customSort(items, index, isDescending) {
          // You can call your method here and below is the sorting code for that column.
          // You can do any chnages here as per your requirement
          items.sort((a, b) => {
              if (index === 'calories') {
                  if (isDescending) {
                      return b.calories - a.calories;
                  } else {
                      return a.calories - b.calories;
                  }
              }
          });

          return items;
        }
    }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<script src="https://unpkg.com/[email protected]/dist/vuetify.js"></script>
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/vuetify.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons">

<div id="app">
    <v-app>
        <v-data-table
                :headers="headers"
                :items="food"
                :custom-sort="customSort"
                hide-actions
        >
            <template slot="items" scope="{ item }">
                <td>{{ item.name }}</td>
                <td>{{ item.calories }}</td>
                <td>{{ item.fat }}</td>
                <td>{{ item.carbs }}</td>
            </template>
        </v-data-table>
    </v-app>
</div>