wittgenstein
wittgenstein

Reputation: 4462

How to sort a computed property in vue.js

I don't know how to sort an already computed array of results.

In Vue, I filter images by their ratio. Now I want to sort the individual results by date, name or whatever is possible.

I tried sorting the array with a method, but this solution does not automatically recalculate and dynamically display the sorted results.

  data() {
    return {
      results: [],
      imgProperties: {
        imgId: [],
        imgRatio: [],
        imgCreateDate: []
      }
    };
  },
  computed: {
    resultsFiltered() {
      if (this.sliderVal == 0) {
        return this.results;
      } else {
        const obj = [];
        const arr = [];
        for (let i = 0; i < this.ratioIndeces.length; i++) {
          const element = this.ratioIndeces[i];
          obj.push(this.results[element]);
          arr.push(this.imgProperties.imgRatio[element]);
        }
        return obj;
      }
    }
  },

There is no sort approach to be seen here.

I would like to know how or where to start.

The code example shows an excerpt of the current structure. The ratio is calculated in the methods.

I would like to sort the array by imgCreateDate and imgRatio.

Upvotes: 2

Views: 11380

Answers (3)

Kenneth
Kenneth

Reputation: 2993

Example of sorting by imgRatio:

<p v-for="result in resultsFiltered | orderBy 'imgRatio'">{{ result.imgRatio }}</p>

or

<p v-for="result in resultsFiltered">{{ result.imgRatio }}</p>
computed: {
    resultsFiltered() {
      if (this.sliderVal == 0) {
        return this.results.sort((a, b) => { return b.imgRatio - a.imgRatio;});
      } else {
        const obj = [];
        const arr = [];
        for (let i = 0; i < this.ratioIndeces.length; i++) {
          const element = this.ratioIndeces[i];
          obj.push(this.results[element]);
          arr.push(this.imgProperties.imgRatio[element]);
        }

        return this.obj.sort((a, b) => { return b.imgRatio - a.imgRatio;});
      }
    }
  },

For Vue2 you can reference on here

Upvotes: 2

wittgenstein
wittgenstein

Reputation: 4462

here is my latest approach to filter the results and sort them by parameters at the same time:

computed: {
  resultsFiltered () {
    return this.built.dataset.filter(img => {
      return this.customFilters.every(key => {
        const parameter = this.params[key]
        const args = parameter.map(val => this.customInputs[val]).slice(1)
        return filterMenus[key](img[parameter[0]], ...args)
      })
    }).sort(this.sortings[this.sortDirection][this.sortType])
  }
},

the single elements:

built.datatset = is an array of objects. Each img is an object.

customFilters = is an array with filter options. like 'ratio' or 'keyword'. So I can filter with every key I got in the list.

customInputs = whatever the user types in. A date range, a ratio, a keyword, a year, ...

sortings = compare img1 to img2

sortDirection = up or down. like 'img2.ratio - img1.ratio'

sortType = alphabetical, numerical, by date or reset to default view

Upvotes: 0

Raymond Camden
Raymond Camden

Reputation: 10857

If your computed property makes use of a data property to control the sort, you could do it like so. First, I created data that includes my original, unsorted data, and a current sort:

  data: {
    origItems:[
      {name:'ray', age:10},
      {name:'apple', age:20},
      {name:'zula', age:9},
    ],
    sortType:''
  },

Then I built my computed to return values based on sortType:

  computed:{
    items() {
      if(this.sortType === '') return this.origItems;
      if(this.sortType === 'name') {
        return this.origItems.sort((a,b) => {
          if(a.name < b.name) return -1;
          if(a.name > b.name) return 1;
          return 0;
        });
      }
      if(this.sortType === 'age') {
        return this.origItems.sort((a,b) => {
          if(a.age < b.age) return -1;
          if(a.age > b.age) return 1;
          return 0;
        });
      }
    }

This could probably be written tighter. I used this layout for testing:

<div id="app" v-cloak>
  <button @click="sort('name')">Sort by Name</button>
  <button @click="sort('age')">Sort by Age</button>
  <ul>
    <li v-for="item in items">{{ item.name}} - {{ item.age }}</li>
  </ul>
</div>

You can see an online example of this here: https://codepen.io/cfjedimaster/pen/eYYMVWr?editors=1011

Upvotes: 1

Related Questions