Reputation: 211
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...
Upvotes: 18
Views: 59131
Reputation: 301
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"
...
>
Upvotes: 9
Reputation: 961
To Build on the response provided by bhaskar
I had to edit the last code sample to the following in order to work on vuetify 2.x. The code sorts the date columns by their epoch time which is stored under the time_stamp
key. The code also allows the default sorting of numbers and strings (strings are sorted alphabetically)
customSort(items, index, isDesc) {
items.sort((a, b) => {
if (index[0] == "date") {
if (!isDesc[0]) {
return a.time_stamp - b.time_stamp;
} else {
return b.time_stamp - a.time_stamp;
}
} else if (!(isNaN(a[index[0]]))) {
if (!isDesc[0]) {
return (a[index[0]] - b[index[0]]);
} else {
return (b[index[0]] - a[index[0]]);
}
} else {
if (!isDesc[0]) {
return (a[index[0]] < b[index[0]]) ? -1 : 1;
} else {
return (b[index[0]] < a[index[0]]) ? -1 : 1;
}
}
});
return items;
}
Upvotes: 3
Reputation: 874
In vuetify 2 just use sortBy="date" and update: sort-desc
<v-data-table
:headers="headers"
:items="acts"
:pagination.sync="pagination"
sortBy="date"
update: sort-desc
>
Upvotes: 1
Reputation: 562
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.
Upvotes: 5
Reputation: 1938
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;
}
Upvotes: 18
Reputation: 842
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>
Upvotes: 6