Shawn Cooke
Shawn Cooke

Reputation: 967

Vue.js filter a list

I am new to Vue.js. I'm trying to display a filtered list based on the value of another object. The select sets the value of the object called activeSet. That value is the key in the sets object. If that keys value is greater than 0 I want to display it in the list and sort by it. Here is my code:

JS

var vm = new Vue({
  el: '#app',
  data: {
    activeSet: 'all',
    computed: {
      activeContents: songs.filter(function(song) {
        return (song[activeSet] > 0);
      })
    },
    songs: {
      a: {
        title: 'Hound Dog',
        all: 0,
        set1: 2
      },
      b: {
        title: 'Long Gone',
        all: 1,
        set1: 0
      },
      b: {
        title: 'Novermber Rain',
        all: 2,
        set1: 3
      }
    },
    sets: {
      all: {
        name: 'All Songs'
      },
      set1: {
        name: 'Acoustic'
      }
    }
  }
})

HTML

<div id="app">
  <select v-model="activeSet">
    <option v-for="(set,key) in sets" :value="key">{{set.name}}</option>
  </select>
  <ul id="menu">
    <li v-for="(song,key) in activeContents" :id="key" :is-active="song.show" :key="key" @click="activeSong=key">{{ song.title }}</li>
  </ul>
</div>

Fiddle Here is the fiddle

Sidenote: If the value is above 0 it needs to be included and then sorted by that value. I haven't even dived into sorting yet so bonus points if you can sort by the value of those that are greater than 0.

Upvotes: 1

Views: 2699

Answers (1)

Bert
Bert

Reputation: 82439

Computed properties are not defined in data, they have their own section in the Vue definition. Additionally, you should use this to reference data properties inside the computed.

If I understand the question correctly, this should work for sorting and filtering.

console.clear()
var vm = new Vue({
  el: '#app',
  data: {
    activeSet: 'all',

    songs: {
      a: {
        title: 'Hound Dog',
        all: 0,
        set1: 2
      },
      b: {
        title: 'Long Gone',
        all: 3,
        set1: 0
      },
      c: {
        title: 'Novermber Rain',
        all: 2,
        set1: 3
      }
    },
    sets: {
      all: {
        name: 'All Songs'
      },
      set1: {
        name: 'Acoustic'
      }
    }
  },
  computed: {
      activeContents(){
        // setup
        let set = this.activeSet
        let filter = k => this.songs[k][set] > 0
        let sorter = (a,b) => this.songs[a][set] - this.songs[b][set]
        
        // filter and sort
        let selectedKeys = Object.keys(this.songs)
          .filter(filter)
          .sort(sorter)
        
        // build new object
        return selectedKeys.reduce((acc, k) => {
          acc[k] = this.songs[k]
          return acc
         }, {})
      }
    },
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.js"></script>
<div id="app">
  <select v-model="activeSet">
    <option v-for="(set,key) in sets" :value="key">{{set.name}}</option>
  </select>
  <ul id="menu">
    <li v-for="(song,key) in activeContents" :id="key" :is-active="song.show" :key="key" @click="activeSong=key">{{ song.title }}</li>
  </ul>
</div>

Upvotes: 2

Related Questions