In VueJS i have an array with plants in my store which looks like this:
state: {
query: '',
tag: '',
plants: [
{
img: "https://cdn.webshopapp.com/shops/29478/files/361778137/650x650x2/hydroplant-monstera-obliqua.jpg",
msg: 'Monstera',
tags: 'easy'},
{
img: "https://mevrouwmonstera.nl/wp-content/uploads/2020/05/Aloe-ferox.jpg",
msg: 'Aloe vera',
tags: 'easy'},
{
img: "https://www.plantje.nl/wp-content/uploads/2022/04/bonsai-ficus-51024.jpg",
msg: 'Bonsai',
tags: 'hard'},
{
img: "https://images.prismic.io/rbnl/0737820a-d068-4588-8898-1c168f49a15d_cactus-plant-in-pot.jpg?auto=compress,format&rect=0,0,1000,1000&w=500&h=500",
msg: 'Cactus',
tags: 'easy'},
],
},
It has msg, on which i filter and tags (easy and hard). I can filter between the names of the plants if I type letters in my input field. Now when I select one of the tags I want the plants with that tag to also be displayed. I want these filters to work in one function so I can filter both these things at the same time. Only the filter of msg is working.
The code in my SearchComponent looks like this:
<template>
<div id="app">
<div>
<form action="#">
<label for="lang">filter between tags:</label>
<select v-model="selected" name="plants" id="lang">
<option class="item plant" v-for="tag in filteredTags" :key="tag" :value="tag">{{tag}}</option>
</select>
<input type="submit" value="Submit" @click="filteredList"/>
</form>
<input type="text" v-model="query" placeholder="Search plants..." />
<div v-for="(plants, index) in $store.state.plants" :key="index">
<div class="item plant" v-for="plant in filteredList" :key="plant.msg">
<img v-bind:src= "plant.img" />
<p>{{ plant.msg }}</p>
<button @click="deletePlants(index)">
Delete plant
</button>
</div>
</div>
</div>
<div class="item error" v-if="query && !filteredList.length">
<p>No results found!</p>
</div>
</div>
</template>
<script>
import { mapMutations, mapGetters } from 'vuex'
export default {
name: 'SearchComponent',
props: {
msg: String
},
data () {
return {
selected: null
}
},
computed: {
...mapGetters([
'filteredList',
'filteredTags',
'filteredTags2'
// ...
]),
query: {
set (value) {
this.setQuery(value);
},
get () {
return this.$store.state.query;
}
},
tag: {
set (value) {
this.setTag(value);
},
get () {
return this.$store.state.tag;
}
},
},
methods: {
...mapMutations([
'setQuery',
'deletePlants',
'setTag'
]),
}
};
</script>
In my store this is the code I havr for the getters and mutations to filter
mutations: {
setQuery(state, value ) {
state.query = value;
},
setTag (state, value) {
state.tag = value
},
addPlants(state, plant) { state.plants.push({ msg: plant }) },
deletePlants (state, index){
state.plants.splice(index, 1);
},
},
getters: {
filteredList (state) {
return state.plants.filter((item) => {
return item.msg.toLowerCase().indexOf(state.query.toLowerCase()) !== -1 && item.tags.toLowerCase().indexOf(state.tag.toLowerCase()) !== -1
})
},
filteredTags (state) {
//todo filter tags and remove duplicates
return Array.from(new Set(state.plants.map( (x) => x.tags)));
}
I want to Use the getter filteredList to be able to filter both these things at one but right now I can still only filter the msg. I also get the following error:
TypeError: handler.apply is not a function
When I try to push the submit button. Can anyone help me with this problem? I also put the code on codesandbox.io: https://codesandbox.io/p/github/michafvdw/plant-searcher/csb-b192tb/plant-searcher?file=%2FREADME.md