Filtering a list by two or more choices in Vue.js 2.0

Since in Vue 2.0 you can no longer bind multiple pipeline filters to a list ( |filterBy

etc.), how should you do this in a computed property if you have two or more separate dropdowns?

I want to sort by album name (from selection 1) and by year (select 2).

<select v-model="albumFilter">
    <option value="All">All</option>
    <option value="Album 1">Album 1</option>
    <option value="Album 2">Album 2</option>
    <option value="Album 3">Album 3</option>
</select>

<select v-model="yearFilter">
    <option value="Year">Year</option>
    <option value="2017">2017</option>
    <option value="2016">2016</option>
    <option value="2015">2015</option>
</select>

<ul>
    <li v-for="review in filterByAlbum" v-if="review.type === 'recordReview'">
        <a :href="review.jsonUrl">
            [[ review.title ]]
        </a>
    </li>
</ul>

      

Vue js code:

data() {
    return {
        pressEntries: [],
        albumFilter: 'All',
        yearFilter: 'Year'
    }
},

filterByAlbum: function() {

    // Select 1 (Album Filter)
    switch (this.albumFilter) {
        case 'All':
            return this.pressEntries;
            break;

        case 'Neither':
            return this.pressEntries.filter(entry => {
                return entry.relatedRecording === null
            });
            break;

        default:
            return this.pressEntries.filter(entry => {
                return entry.relatedRecording === this.albumFilter
            });     
    }

    // Select 2 (Year Filter)
    if (this.yearFilter === 'Year') {
        return this.pressEntries;
    }
    else {
        return this.pressEntries.filter(entry => {
            let postDate = new Date(entry.postDate.date);
            return JSON.stringify(postDate.getFullYear()) === this.yearFilter;
        });
    }
}

      

The data model pressEntries

receives data from an API that I didn't bother with, including the code for. Each block of code for each selection filter works on its own, but not together.

If filterByAlbum

in a loop it v-for

refers to a computed property that then refers to the data model pressEntries

, is it possible to have two computed properties that pass v-for

(like filterByAlbum

"and" filterByYear "for example)? Or I need to figure out how to filter all the results in one massive computed property ?

+1


source to share


2 answers


Here is an example computed that will work. You can move albumFilter

and yearFilter

in their own methods. Essentially, using this technique, you can collect as many filters as you like.

function filterByAlbum(){

  const albumFilter = entry => 
           (this.albumFilter == 'All') || 
           (this.albumFilter == 'Neither' && !entry.relatedRecording) ||
           (entry.relatedRecording === this.albumFilter);

  const yearFilter = entry => 
         (this.yearFilter == 'Year') || 
         (new Date(entry.postDate.date).getFullYear() == this.yearFilter);

  const reducer = (accumulator, entry) => {
    if (albumFilter(entry) && yearFilter(entry))
      accumulator.push(entry);
    return accumulator;
  }

  return this.pressEntries.reduce(reducer, []);
}

new Vue({
  el: "#app",
  data() {
    return {
        pressEntries,
        albumFilter: 'All',
        yearFilter: 'Year'
    }
  },
  computed:{
    filterByAlbum
  }
})

      



I had to guess your data structure, but here's a working example .

+3


source


This is my solution: You can add 3 Selectbox easily

https://codepen.io/anon/pen/PjOoEN



function() {
    var vm = this;
    var category = vm.selectedCategory;
    var gender = vm.selectedGender;

    if(category === "All" && gender === "All") {
        return vm.people;
    } else {
        return vm.people.filter(function(person) {
            return  (category === 'All' || person.category === category) && (gender === 'All'  || person.gender === gender);     
        });
    }
}

      

0


source







All Articles