Reputation: 209
I'm playing around with Vue.js and I am struggling to figure out how to sort a list while I am clicking a button.
Actually, I did succeed to sort the list using orderedBeers method; when I click the button I can see the ordered list in the inspector but I can't change the data in HTML.
Every recommendation is appreciated. Thank you in advance.
<template>
<div>
<div class=" main-conte" >
<transition-group name="fade" tag="div" id="container" class=" row " >
<figure v-for="(value,index) in toBeShown" id="page-wrap" :key="index" class="beer-container col-xs-6 col-sm-6 col-lg-4 col-xl-2" >
<a >
<img @click="goTodetail(value.id)" class="logo lazy img-responsive loaded" v-bind:src="getMissingImg(index)"/>
<figcaption>
<div class="beer-title">{{value.name}}</div>
<div class="beer-availability"> {{value.tagline}}</div>
<div class="learn-more">
<h4 class="beer-info-title">Format</h4>
<span class="serving-icons"></span>
<div class="serving">
<i v-if="value.abv >= 0 && value.abv <=6 " class="fas fa-wine-glass-alt"></i>
<i v-if="value.abv >= 6 && value.abv <=7" class="fas fa-glass-cheers"></i>
<i v-if="value.abv >= 7 && value.abv <=100" class="fas fa-wine-bottle"></i>
<span class="measure">{{value.abv}}</span>%
</div>
</div>
</figcaption>
</a>
</figure>
</transition-group>
<div class=prev-next>
<button @click="orderedBeers">Click Me!</button>
<button class="prev" @click="prevPage" :disabled="currentPage==1">
<i class="fas fa-angle-double-left"></i></button>
<button class="next" @click="nextPage" :disabled="currentPage == totalPages">
<i class="fas fa-angle-double-right"></i> </button>
</div>
</div>
<div>
</div>
</div>
</template>
<script>
import { mdbView, mdbMask } from "mdbvue";
import FadeTransition from "./fade-transition.vue";
export default {
name: "home",
components: {
mdbView,
mdbMask,
FadeTransition
},
data() {
return {
items: [],
currentPage: 1,
};
},
computed: {
//show more less products
toBeShown() {
return this.items.slice(0, this.currentPage * 5);
},
totalPages() {
return Math.ceil( this.items.length / 4);
},
},
mounted() {
this.fetchData();
},
methods: {
fetchData: function() {
const myRequest = new Request("https://api.punkapi.com/v2/beers");
fetch(myRequest)
.then(response => {
return response.json();
})
.then(data => {
this.items = data;
console.log(this.items);
})
.catch(error => {
console.log(error);
});
},
getMissingImg(index) {
return this.images[index];
},
nextPage(){
if(this.currentPage < this.totalPages) this.currentPage++;
// this.scrollToEnd();
},
prevPage(){
this.currentPage = this.currentPage - 1 || 1;
// this.scrollToEnd();
},
goTodetail(prodId) {
let proId=prodId
this.$router.push({name:'blog',params:{Pid:proId}})
},
orderedBeers: function () {
console.log(_.orderBy(this.toBeShown, 'name', 'asc'));
return _.orderBy(this.toBeShown, 'name', 'asc');
},
}
};
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
Upvotes: 0
Views: 4252
Reputation: 10400
You're almost there. You just need to use another computed property that sorts the list and use that in your v-for
.
Modify the template to:
<figure v-for="(value,index) in toBeShownOrdered" id="page-wrap" :key="index" >
<button @click="orderByName = !orderByName">Click Me!</button>
And the component to:
// Add in data:
orderByName: false,
// Add in computed
toBeShownOrdered() {
return this.orderByName ? _.orderBy(this.toBeShown, 'name', 'asc') : this.toBeShown;
}
See also here: https://v2.vuejs.org/v2/guide/list.html#Displaying-Filtered-Sorted-Results
Upvotes: 1
Reputation: 14191
Your source of data is the computed property toBeShown
. If you want your data to be presented sorted toBeShown
must return that.
In orderedBeers
you are sorting the items returned
by toBeShown
when you should be changing toBeShown
to use the sorted data itself.
Change orderedBeers
to update data.items
to reflect the new ordering:
orderedBeers: function () {
this.data.items = _.orderBy(this.data.items, 'name', 'asc')
}
This will sort the entire item list and not only the current displayed page.
Or
Use a sorting flag and move the sorting login inside toBeShown
data() {
return {
items: [],
currentPage: 1,
sorted: false
}
}
...
orderedBeers: function () {
this.sorted = true
}
...
toBeShown() {
return this.sorted ? _.orderBy(this.data.items, 'name', 'asc').slice( 0, this.currentPage) : this.items.slice(0, this.currentPage * 5);
}
This will also sorts all of the items, but can change the code a bit to only sort the current displayed page
toBeShown() {
let items = this.items.slice(0, this.currentPage * 5)
return this.sorted ? _.orderBy(items, 'name', 'asc') : items
}
Upvotes: 1