0
votes

After the user goes back from viewing the item (question) component, I am trying to keep the user's filtered list of questions based on two selects (category and sub category) and selected page from pagination in the questions list component.

I am new to Vue environment and not sure if I am following the best practice but here what I have tried to do:

1- I tried using the event bus, but I reached a point where I am able to get an object that contains the question category object to the main component and then it would be used as an attribute inside of the Onchange method which normally be triggered after the category select event happens. I was able to show the user the same list of filtered items, however, the problem with this approach that: a- I can not update the select values to show the selected options which gave the questions list. I have tried to get the selected element using the ref attributes, however the select element is undefined even though I put it in the mounte stage of the life cycle. It works with an ugly hack by using a setTimeout method and it shows the element after one second. b- The filtered list of items has pagination and this approach does not show the user the same page that they picked the item from. c- Calling the server again

2- I tried to store a global value in mixins file, however after saving the value in the mixins file and even though the object value is received in the mixins file but after updating the mixins data and then calling it from the questions list, it returns an empty object.

3- I tried using keep-alive

Code for approach 1:

The category object is eager loaded with the question using an event emit. After the user goes back from viewing the question I pass the category object with the event using beforeDestroy method:

beforeDestroy () {
      EventBus.$emit('backToQuestions', this.question.category);
  }

This is how the category object look like:

{…}=>
__ob__: Object { value: {…}, dep: {…}, vmCount: 0 }
created_at: 
id: 
parent_id: 
title: 
updated_at: 

This is how I populate the filtered questions list

created () {
    EventBus.$on('backToQuestions', category => {
          this.onChange(category)
      });
    this.fetch(`/categories`);
}

My select:

<div class="col-md-4">
  <select ref="main" class="form-control" v-model="mainSelected"  @change="onChange(mainSelected)">
   <option  disabled value="">Questions Category (All)</option>
   <option v-for="option in parentCategories" :value="option">{{ option.title }}</option>
  </select>
</div>
<div  v-if="subCategory" class="btn-group">
  <select class="form-control"  v-model="subSelected"  @change="onChange(subSelected)">
   <option  disabled value="" selected >{{ categoryTitle }} Qs Categories</option>
   <option v-for="option in childCategories" :value="option">{{ option.title }}</option>
  </select>
</div>

The following is my onChange method just for reference:

  onChange(option) {
        this.categoryOption = option;
        this.dataReady = false;
        this.subCategory = true;
        this.questions= {};
        this.questionsArray =[];
        this.categoryTitle = option.title;
        this.categoryId = option.id;
        if(option.children){
            this.childCategories = option.children;
        }
        axios.get(`/categories/${this.categoryId}`)//getting the category questions
        .then(({data}) =>  {
            this.questions = data;
            this.questionsArray.push(...data.data);
            this.nextUrl = data.next_page_url;
            this.dataReady = true;
            this.emptyCheck(this.questionsArray);
        })
        .catch((err) => {
           swal("Failed!", err.response.data.message, "info");
           this.$router.push('dashboard') ;
        })
      }

$refs of the select divs always return undefined unless I used setTimeout.

Code for approach 2:

After including the mixins file in both components I put the following code in mixins:

  setCategory (questionCategory) {
       console.log("TCL: setCategory -> questionCategory", questionCategory)
        this.category = questionCategory;
       console.log("TCL: setCategory -> this.category", this.category)
        }
        ,
        getCategory () {

            return this.category ;
        }

The value of the object received by the set method is correct but after updating the mixins data method this.category is returning the following only:

__ob__: Object { value: {…}, dep: {…}, vmCount: 0 }

i.e. without the category object details. I tried to stringify the object and then call it, this.category shows an empty variable.

3- Using keep-alive, however it does not work, I tried to wrap both the router-view and router-link.

   <keep-alive include="questions-list">
       <router-link  to="/questions-list" class="nav-link">
           <i class="nav-icon fas fa-question-circle  orange"></i>
           <p>
               Questions
           </p>
       </router-link>
   </keep-alive>

I even tried using include the name of the questions list component with no result.

Sorry for the long question but I have been stuck for a while with this and it is the core of my application.

1
Could you perhaps add a reproducable example on something like JSFiddle or Codepen?D Malan
Thank you @DelenaMalan for your comment, it works well now, I will post the answer.user3384815

1 Answers

0
votes

I am now using keep-alive approach. The silly mistake was that I only named the component when I declared my routes.

{ path: '/questions-list', name:"questions-list", component: require('./components/qa/Questions.vue')}

For those who are facing the same problem, you should declare the name of the component inside of the component export object like the following:

export default {
    name: 'questions-list',

    data () {
        return {

        }
}