3

I have a SPA where I show array of pokemon using v-for, with the option to filter those lists by type or generation. I have a button that clears the filters (sets the type to '' and generation to generation 1), but the v-for loop doesn't re-render the array after the filters are cleared. I've logged the function that returns the array of pokemon to confirm it's working, but Vue JS doesn't render the results. I'm not sure how to proceed.

<div class="pokemon"
            v-for="pokemon in filteredPokemon"
            :key="pokemon.id">
                <h2>{{ pokemon.name }}</h2>
</div>

<script>
import Pokemon from '../pokeData'

export default{
props: ['searchFilters'],
data(){
        return{
            allPokemon: [],
        }
    },
created(){
            this.allPokemon = Pokemon.getPokemon('gen1');
    },
computed: {
        filteredPokemon: function(){ 
            if(this.searchFilters.type){
                if(this.searchFilters.type === ''){
                    return this.allPokemon
                }
                return this.allPokemon.filter(pokemon => {
                    if(pokemon.types.length === 2){
                        if(pokemon.types[0].type.name == this.searchFilters.type || pokemon.types[1].type.name == this.searchFilters.type){
                            return true
                        }
                    }
                    else if(pokemon.types[0].type.name == this.searchFilters.type){
                            return true
                        }
                })
            }
            return this.allPokemon
        }
    },
watch:{
        'searchFilters.generation': function(generation){
            this.allPokemon = Pokemon.getPokemon(generation)
        }
    }
}
}
</script>
2
  • 2
    You probably modifying searchFilters attributes and Vue don't know about it. Look at vuejs.org/v2/guide/reactivity.html Commented May 21, 2020 at 13:54
  • You're right, the clear filters button sets searchFilters.generation to 'gen1' and searchFilters.type to ''; but they are computed properties, and there's a watcher on searchFilters.generation. They react fine when they're computed, but vuejs doesn't re-render the arrays when they're set back to the original array. I've read the documentation you linked but don't understand how using $set would resolve this Commented May 21, 2020 at 14:13

1 Answer 1

2

farincz is right, you are changing the attributes of allPokemon with the function call to getPokemon and Vue.JS can't find the change (documentation), therefore it's a caveat and you would need to handle this in a different way because Vue doesn't support the way you want it.

I would filter all pokemons with a filter method with a computed value and bind the filter value to a data property:

HTML:

<template>
  <div>
    <textarea v-model="text" name="filter" cols="30" rows="2"></textarea>
    <div class="pokemon" v-for="pokemon in filteredPokemon" :key="pokemon.id">
      <h2>{{ pokemon.name }}</h2>
    </div>
  </div>
</template>

JS file:

new Vue({
  el: "#app",  
  data(){
    return{
      text: '',
      pokemons: [
              {gen: 'gen1', name: 'psyduck', id: '1'},
              {gen: 'gen1', name: 'charizard', id: '2'},
              {gen: 'gen1', name: 'pikachu', id: '3'},
              {gen: 'gen2', name: 'togapi', id: '4'}   
            ]
    }
  },
  computed: {
    filteredPokemon() {
      if(this.text === '') return this.pokemons
      return this.pokemons.filter(x=>x.gen === this.text)
    }
  }
})

here's the jsfiddle to play around.

Sign up to request clarification or add additional context in comments.

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.