Home > Software engineering >  Unable to Filter By Category in A Forum
Unable to Filter By Category in A Forum

Time:11-29

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.

  • Related