Ioan Dimi
Ioan Dimi

Reputation: 209

Order by the name a list in Vue.js while clicking a button

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

Answers (2)

bernie
bernie

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

Radu Diță
Radu Diță

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

Related Questions