0

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>

4 Answers 4

3

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;
        });
      }
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

thanks for correcting me, before this i was using computed property only. but i was not doing "const self = this;" . I was directly using this.currentFilter. i wonder why we need to do this ?
If you want to use this then you can use ES6 notation of in callback function in Array.filter like this.pdList.filter(game => { return this.currentFilter === game.genre; });
0

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;
        });
    }
}

Comments

0

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.

Comments

0

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;
            });
        }
        }


        }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.