spratap124
spratap124

Reputation: 171

unable to filter array of objects in Vue js

I want to filter the games by genre. pdList is the array of objects(games).To do this i'm using Array.filter(). but its not working. below is the code. Correct me if my approach is wrong. its not giving any error also in the console.

Vuejs code:

new Vue({
el: "#app",
data: {
    currentFilter:"all",
    pdList:[,
            {
            "title": "Double Dragon: Neon",
            "url": "/games/double-dragon-neon/xbox-360-131320",
            "platform": "Xbox 360",
            "score": 3,
            "genre": "Fighting",
            "editors_choice": "N",
            "release_year": 2012
            },
            {
            "title": "Guild Wars 2",
            "url": "/games/guild-wars-2/pc-896298",
            "platform": "PC",
            "score": 9,
            "genre": "RPG",
            "editors_choice": "Y",
            "release_year": 2012
            }]
},
methods: {
    filterByGenre:function(filterby){
    this.currentFilter = filterby;
    },
    filteredGames:function(pdList){
    console.log("inside filtergames");
    if(this.currentFilter == "all"){

        return pdList;
    }else{
        return  pdList.filter(function(game){
        console.log(this.currentFilter);
        return game.genre == this.currentFilter;
        });
    }
    }
}
})

HTML

<div id="app">
  <h2>Game Lister:</h2>
  <ol>
    <li v-for="game in filteredGames(pdList)">

      {{game.genre}}

    </li>
  </ol>
</div>

 <select v-model="currentFilter">
  <option value="all">all</option>
  <option value="Platformer">Platformer</option>
  <option value="Platformer">Puzzle</option>
  <option value="Platformer">Sports</option>
  <option value="Platformer">Strategy</option>

  </select>

Upvotes: 0

Views: 5955

Answers (4)

spratap124
spratap124

Reputation: 171

added the search feature also.

filteredGames () {
            const self = this;
        //for searching
        if(this.search.length > 0){
            return self.pdList.filter(function(game) {
                console.log(game.title)
               return game.title.toLowerCase().indexOf(self.search.toLowerCase()) >= 0;
            });
        }else{
            if (self.currentFilter === 'all') {
            return self.pdList;
        } else {
            return self.pdList.filter(function(game) {
               return self.currentFilter === game.genre;
            });
        }
        }


        }

Upvotes: 0

Himanshu Mittal
Himanshu Mittal

Reputation: 804

You can try this approach as well after correcting the syntax issues as mentioned by @Naiful.

Template :

<div id="app">
 <h2>Game Lister:</h2>
 <ol>
   <li v-for="game in filteredGames">
    {{game.genre}}
   </li>
 </ol>
 <select v-model="currentFilter">
  <option value="all">all</option>
  <option value="Platformer">Platformer</option>
  <option value="Platformer">Puzzle</option>
  <option value="Platformer">Sports</option>
  <option value="Platformer">Strategy</option>
 </select>
</div>

You can then put a watch on your currentFilter model and invoke your filterByGenre function to update filteredGames.

VueJs Code :

new Vue({
 el: "#app",
 data (){
  return {
   currentFilter:"all",
   filteredGames : [],
   pdList:[{
        "title": "Double Dragon: Neon",
        "url": "/games/double-dragon-neon/xbox-360-131320",
        "platform": "Xbox 360",
        "score": 3,
        "genre": "Fighting",
        "editors_choice": "N",
        "release_year": 2012
        },
        {
        "title": "Guild Wars 2",
        "url": "/games/guild-wars-2/pc-896298",
        "platform": "PC",
        "score": 9,
        "genre": "RPG",
        "editors_choice": "Y",
        "release_year": 2012
        }]
  }
 },
 created (){
   this.filterByGenre();
 },
 watch : {
  'currentFilter' (){
   this.filterByGenre();
  }
 },
 methods: {
  filterByGenre (){
    this.filteredGames = [];
    if(this.currentFilter == "all"){
     this.filteredGames = this.filteredGames.concat(this.pdList);
    }else{
     this.filteredGames = this.pdList.filter(game => game.genre == this.currentFilter);
    }
  }
 }
});

P.S. - In your vue code, data should be a function which returns an object like recommended in VueJS official documentation.

Upvotes: 0

Nafiul Islam
Nafiul Islam

Reputation: 1220

The idea isn't a correct one. Some flaws in the code:

In Template:

  1. Select option is out of div#app - will result select in not being shown
  2. All options but 'all' have same value in select

In ViewModel:

  1. pdList in data() has started with [, - which will break the code
  2. A simple computed function will do it all - and you haven't used any of the methods you used in your template

The solution would be:

Template

<div id="app">
  <h2>Game Lister:</h2>
  <ol>
    <li v-for="game in filteredGames">{{game.title}}</li>
  </ol>

  <select v-model="currentFilter">
    <option value="all">all</option>
    <option value="Fighting">Fighting</option>
    <option value="RPG">RPG</option>
  </select>
</div>

ViewModel

data: {
    currentFilter: "all",
    pdList: [{
      "title": "Double Dragon: Neon",
      "url": "/games/double-dragon-neon/xbox-360-131320",
      "platform": "Xbox 360",
      "score": 3,
      "genre": "Fighting",
      "editors_choice": "N",
      "release_year": 2012
    }, {
      "title": "Guild Wars 2",
      "url": "/games/guild-wars-2/pc-896298",
      "platform": "PC",
      "score": 9,
      "genre": "RPG",
      "editors_choice": "Y",
      "release_year": 2012
    }]
},
computed: {
    filteredGames () {
        const self = this;
      if (self.currentFilter === 'all') {
        return self.pdList;
      } else {
        return self.pdList.filter(function(game) {
          return self.currentFilter === game.genre;
        });
      }
    }
}

Upvotes: 3

Arielle Nguyen
Arielle Nguyen

Reputation: 3162

A method invocation will always run the function whenever a rerender happens. To know that it depends on this.pdList, you don't need to parse it in.

HTML

<li v-for="game in filteredGames()">

  {{game.genre}}

</li>

Vuejs

filteredGames:function(){
    console.log("inside filtergames");
    if(this.currentFilter == "all"){

        return this.pdList;
    } else {
        return  this.pdList.filter(function(game){
          console.log(this.currentFilter);
          return game.genre == this.currentFilter;
        });
    }
}

Upvotes: 0

Related Questions