Reputation: 1368
I have a data structure here which i have divided into headers and the items. I am trying to apply a custom sort for which i have the logic down and i have created a method for it but i am not able to figure out how to apply that sort methods based on the name and grades individually. Here is a link to the codepen.
new Vue({
el: '#app',
data() {
return {
headers: [{
text: 'Name',
value: 'Name'
},
{
text: 'Grades',
value: 'grades'
},
],
labels: ['Andy', 'Max', 'John', 'Travis', 'Rick'],
Grades: [99, 72, 66, 84, 91]
}
},
computed: {
tableItems() {
let items = [],
this.labels.forEach((label, i) => {
let item = {}
item.name = label
item.grades = this.Grades[i]
items.push(item)
console.log(items)
})
return items
}
},
methods: {
sortBy(prop) {
this.tableItems.sort((a, b) => a[prop] < b[prop] ? -1 : 1)
}
}
})
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/babel-polyfill/dist/polyfill.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.css" rel="stylesheet" />
<div id="app">
<v-app id="inspire">
<v-container>
<v-layout>
<v-flex v-for="(header, i) in headers" :key="header.text" xs4 py-1>
<span>{{ header.text }}
<v-icon small @click="sortBy(this.labels)">arrow_upward</v-icon>
</span>
</v-flex>
<v-layout v-for="item in tableItems" :key="item.name">
<v-flex xs4 py-1>
<span>{{ item.name }}</span>
</v-flex>
<v-flex xs4 py-1>
<span>{{item.grades}}</span>
</v-flex>
</v-layout>
</v-layout>
</v-container>
</v-app>
</div>
Now while keeping the data structure and everything the way it is, how can i make the method on the v-icon work for grades and name individually?
Upvotes: 1
Views: 1552
Reputation: 4656
Here are a few things I did to make it work.
sortKey
on the basis of which your data will be sortedsortKey
as an argument when you click on your spantableItems
use the sort key to sort your dataLook for the comments in the code below
<div id="app">
<v-app id="inspire">
<v-container>
<v-layout>
<v-flex v-for="header in headers" :key="header.text" xs4 py-1>
<span>
{{ header.text }}
<v-icon small @click="sortBy(header.value)">arrow_upward</v-icon>
***** changed the value for name (from Name to name) ****
</span>
*** everything else is the same ***
</v-layout>
</v-container>
</v-app>
</div>
The script looks like this
<script>
export default {
name: "app",
data() {
return {
headers: [
{ text: "Name", value: "name" }, // changed this to name
{ text: "Grades", value: "grades" }
],
labels: ["Andy", "Max", "John", "Travis", "Rick"],
Grades: [99, 72, 66, 84, 91],
sortKey: "" // added a sortKey,
};
},
computed: {
tableItems() {
let retVal = this.labels.map((label, i) => {
return {
name: label,
grades: this.Grades[i]
};
});
// if there is a sortKey use that
if (this.sortKey) {
retVal.sort((a, b) =>
a[this.sortKey] < b[this.sortKey] ? -1 : 1
);
}
return retVal;
}
},
methods: {
sortBy(prop) {
// assign sortKey here, this assignment will retrigger the computation
this.sortKey = prop;
console.log(prop);
}
}
};
</script>
************* EDIT *****************
add in a direction variable for your sorting order (1 is ascending, -1 is descending)
so your data would look like
data() {
return {
headers: [
{ text: "Name", value: "name" }, // changed this to name
{ text: "Grades", value: "grades" }
],
labels: ["Andy", "Max", "John", "Travis", "Rick"],
Grades: [99, 72, 66, 84, 91],
sortKey: "" // added a sortKey,
direction: 1 // for ascending order
};
},
now in your program, if you are clicking on the same thing, you need to change your ascending or descending state, do that in your method
methods: {
sortBy(prop) {
// if the sortKey was prop to begin with
if (this.sortKey === prop) {
this.direction *= -1 // change direction to -ve or positive
}
// assign sortKey here, this assignment will retrigger the computation
this.sortKey = prop;
console.log(prop);
}
}
Finally, use your direction in the sorting
computed: {
tableItems() {
let retVal = this.labels.map((label, i) => {
return {
name: label,
grades: this.Grades[i]
};
});
// if there is a sortKey use that
if (this.sortKey) {
retVal.sort((a, b) =>
this.direction * // here multiply by the direction
(a[this.sortKey] < b[this.sortKey] ? -1 : 1)
);
}
return retVal;
}
},
And You will be done
Upvotes: 1