Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use vutify's custom sort?

I'd like to use custom-sort in my data table. My goal is to sort the table DESC as opposed to the default ASC. But I don't know-how.

This is the start of my data table component:

  <v-data-table
  :headers="headers"
  :items="acts"
  hide-actions
  class="elevation-1"
  >
  <template slot="items" slot-scope="props">

    <td>{{ props.item.id }}</td>
    <td>{{ props.item.name }}</td>
    <td class="text-xs-center">{{ props.item.provider.id }}</td>
    <td class="text-xs-center">{{ props.item.category.name }}</td>
    <td class="text-xs-center">{{ props.item.budget }}</td>
    <td class="text-xs-center">{{ props.item.location.name }}</td>
    <td class="text-xs-center">{{ props.item.deets }}</td>
    <td class="text-xs-center">{{ props.item.keeping_it_100 }}</td>
    <td class="text-xs-center"><img width="50" height="50" :src="props.item.inspiration.inspiration"></td>
    <td class="justify-center layout px-0">....

And this is the script I'm using:

<script>
  export default {
    data () {
      return {

        dialog: false,
        customerSort: {
          isDescending: true,// I tried this? as the kabab format throws an error
        },
        headers: [
            { text: 'ID', value: 'id'},
            { text: 'Name', value: 'name' },  
            { text: 'Provider', value: 'provider' },
            { text: 'Category', value: 'category' },
            { text: 'Budget', value: 'budget' },
            { text: 'Country', value: 'location', sortable: true },
            { text: 'Keeping it 100%', value: 'keeping_it_100', sortable: false },
            { text: 'deets', value: 'deets', sortable: false },
            { text: 'inspiration', value: 'inspiration', sortable: false },
            { text: 'Cover', value: 'cover', sortable: false },
            { text: 'Actions', value: 'actions', sortable: false }
        ],

According to docs it is a function prop. But I haven't found an example on how to pass it.

This is a screenshot of the function...

like image 263
Seif Avatar asked Oct 06 '18 12:10

Seif


4 Answers

You can use a function like this-

customSort(items, index, isDesc) {
  items.sort((a, b) => {
    if (index === "date") {
      if (!isDesc) {
        return compare(a.date, b.date);
      } else {
        return compare(b.date, a.date);
      }
    }
  });
  return items;
}

Where the compare is a function which compares a.date and b.date and returns 1 or -1

isDesc is a variable passed by the table which tells in what order does the user want to sort it. If you want to sort in desc, just use !isDesc in the if-else condition

To use this in your template just use

<v-data-table
  :headers="headers"
  :items="Data"
  :custom-sort="customSort"
>
  <template slot="items" slot-scope="props">
    <td class="font-weight-black">{{ props.item.date }}</td>
    <td class="text-xs-right">{{ props.item.time }}</td>
    <td class="text-xs-right">{{ props.item.name }}</td>
  </template>
</v-data-table>

To make sure your other fields still work with the normal sort use

customSort(items, index, isDesc) {
      items.sort((a, b) => {
        if (index === "date") {
          if (!isDesc) {
            return dateHelp.compare(a.date, b.date);
          } else {
            return dateHelp.compare(b.date, a.date);
          }
        } else {
          if (!isDesc) {
            return a[index] < b[index] ? -1 : 1;
          } else {
            return b[index] < a[index] ? -1 : 1;
          }
        }
      });
      return items;
    }
like image 160
Bhaskar Avatar answered Nov 15 '22 08:11

Bhaskar


Based on this answer code about custom-filter, I tried using custom-sort.
Please refer to this answer if you apply it to your code.

By the following code, I have confirmed sorting when I click 'Calories' header.
My CodePen

new Vue({
    el: '#app',
    data() {
        return {
            food: [
                { name: 'Bakchoi', type: 'vegetable', calories: 100 },
                { name: 'Pork', type: 'meat', calories: 200 },
                { name: 'Chicken Thigh', type: 'meat', calories: 300 },
                { name: 'Watermelon', type: 'fruit', calories: 10 },
            ],
            headers: [
                { text: 'Name', align: 'left', value: 'name' },
                { text: 'Food Type', align: 'left', value: 'type' },
                { text: 'Calories', align: 'left', value: 'calories' },
            ],
            search: '',

        };
    },
    methods: {
        customSort(items, index, isDescending) {
          // The following is informations as far as I researched.
          // items: 'food' items
          // index: Enabled sort headers value. (black arrow status).
          // isDescending: Whether enabled sort headers is desc
          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://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-select
                label="Food Type"
                :items="['vegetable', 'meat', 'fruit']"
                v-model="search"
        ></v-select>

        <v-data-table
                :headers="headers"
                :items="food"
                :search="search"
                :custom-sort="customSort"
                hide-actions
        >
            <template slot="items" scope="{ item }">
                <td>{{ item.name }}</td>
                <td>{{ item.type }}</td>
                <td>{{ item.calories }}</td>
            </template>
        </v-data-table>
    </v-app>
</div>
like image 30
kuromoka Avatar answered Nov 15 '22 08:11

kuromoka


Although it's an old question ...

For special sorting of only one column, you could use the property sort in the headers array. See also https://vuetifyjs.com/en/api/v-data-table/#headers

Like so:

// in data ... 
headers: [
... 
{
    text: "Date",
    sortable: true,
    value: "date",
    sort: (a, b) => a.time_stamp - b.time_stamp
 },
 ...
]

use it like

<v-data-table
 :headers="headers"
...
>
like image 7
joergwork Avatar answered Nov 15 '22 08:11

joergwork


NOTE: the following answer is for Vuetify 1.5.x

A little late to the party here, if all you want to do is sort descending by a single field, then custom-sort it not what you want to use, you're better off using the :pagination.sync prop

Custom sort is used when you want to change the behaviour of the comparison function (e.g sorting based off the reverse or lowercase version of a string, or proper sorting of date strings in the format 'DD-MM-YYYY').

If you want to use the default descending functionality, use the :pagination.sync prop, like so:

<v-data-table
  :headers="headers"
  :items="acts"
  :pagination.sync="pagination"
>
    <template v-slot:items="props">...</template>
</v-data-table>

In your script, set pagination:

data () {
  return {
    pagination: {
      sortBy: 'id', // The field that you're sorting by
      descending: true
    }
  }
}

This specifies that you want the table to be initially sorted by descending id - id can be changed to any field name in the dataset.

It's worth noting that this only specifies the default behaviour, and if you have sorting enabled for your other headers, users can still sort the table by any field.

like image 5
naffarn Avatar answered Nov 15 '22 07:11

naffarn