I've just reached the end of my forum project, however I've hit a wall with filtering by category.
What it needs to do is when I click on the category within the sidebar, it'll instantly filter all posts / questions by the selected category.
I can't figure out how to do this, as every method I've tried just hasn't worked.
Hopefully somebody will be able to help me, will post code below for forum.vue and AppSidebar.vue - If anything else is needed, please ask and i'll edit this post
Forum.Vue
<template>
<v-container fluid grid-list-md>
<v-layout row wrap>
<v-flex xs8>
<question v-for="question in filterByCat(id)" :key="question.path" :question=question></question>
<v-spacer></v-spacer>
<div class="text-xs-center">
<v-pagination v-model="meta.current_page" :length="meta.last_page" @input="changePage"></v-pagination>
</div>
</v-flex>
<v-flex xs4>
<app-sidebar></app-sidebar>
</v-flex>
</v-layout>
</v-container>
</template>
<script>
import question from './question'
import AppSidebar from './AppSidebar'
export default {
data() {
return {
questions: {},
meta: {},
id: {},
}
},
components: {
question,
AppSidebar
},
created() {
this.fetchQuestions()
this.listen()
},
methods: {
filterByCat(id){
return this.questions.filter(question => question.category_id === id)
},
fetchQuestions(page) {
let url = page ? `/api/question?page=${page}` : '/api/question'
axios.get(url)
.then(res => {
this.questions = res.data.data
this.meta = res.data.meta
})
.catch(error => console.log(error.response.data))
},
changePage(page) {
this.fetchQuestions(page)
},
listen(){
EventBus.$on('filterCategory', () => {
this.filterByCat(id)
})
},
}
}
</script>
<style>
</style>
AppSidebar.vue
<template>
<v-card>
<v-toolbar color = "cyan" dark dense class="mt-4" elevation="2">
<v-toolbar-title>Forum Categories</v-toolbar-title>
</v-toolbar>
<v-list>
<v-list-item v-for="category in categories" :key="category.id">
<v-card-actions>
<v-btn text color="blue" @click="filterCategory">{{category.name}}</v-btn>
</v-card-actions>
</v-list-item>
</v-list>
</v-card>
</template>
<script>
export default {
data(){
return {
categories:{}
}
},
created(){
axios.get('/api/category')
.then(res => this.categories = res.data.data.sort((a, b) => a.name.localeCompare(b.name)))
},
methods: {
filterCategory(){
EventBus.$emit('filterCategory')
}
}
}
</script>
<style>
</style>
CodePudding user response:
Firstly, you're not actually emitting the category id in your AppSidebar.vue
component so Forum.vue
isn't ever going to know what the id
is and therefore can't filter anything with it.
Update AppSidebar.vue
so that you're actually emitting the id:
<v-btn text color="blue" @click="filterCategory(category.id)">{{category.name}}</v-btn>
//...
filterCategory(id) {
EventBus.$emit('filterCategory', id);
}
The next problem is that your listener is just calling the filter method (which just returns the filtered list, it's not going to update anything) also id
would have been undefined.
A computed property would be more suitable for this.
Create a computed property called filteredQuestions
in your Forum.vue
:
computed: {
filteredQuestions() {
if (this.id) {
return this.questions.filter(question => question.category_id === this.id)
}
return this.questions;
}
},
Update your event listener to simply set the id
:
listen() {
EventBus.$on('filterCategory', (id) => {
this.id = id;
})
},
Then update your v-for
to be:
<question v-for="question in filteredQuestions"
Lastly, you can remove your filterByCat
method.