1

I need to be able to switch between lists to display in vuejs. So something like:

  <app-card
        v-for="card in cardsCache[currentCategory]"
        :key="card"
        :affiliateLink="card.affiliateLink"
        :author="card.author"
        :category="card.category"
        :comments="card.comments"
        :description="card.description"
        :downvotes="card.downvotes"
        :id="card.id"
        :imageUrl="card.imageUrl"
        :timeCreated="card.timeCreated"
        :title="card.title"
        :upvotes="card.upvotes"
        @click-card="clickCard"
        @click-upvote="clickUpvote"
        @click-downvote="clickDownvote"
        @click-affiliateLink="clickAffiliateLink"
        @click-comments="clickComments"
        @click-save="clickSave"
      ></app-card>

Notice what I'm doing with the vfor, I'm accessing an object with the currentCategory variable which could change at anytime. This sort of works but has issues. When I initially switch category it will render as expected, but if I continue to add to the array for the recently switched to category it will not continue to render to render what's being added to the list. And yes I checked the list is actually having items be added. I've found that any lists added to the cardsCache object as a literal, so: cardsCache: {"popular": []} then this issue does not happen for that list. I've also found that if I switch to and from the same list it will suddenly render all the new items added to it. It's like vuejs has trouble watching objects. I would think what I'm trying to do is fairly basic but I haven't been able to find any examples of people doing this.

Below is how I'm adding data to be displayed:

      const self = this;
      if (Util.nullOrUndefined(self.cardsCache[category])) {
        self.cardsCache[category] = [];
      }
      if (self.previousCategory != self.currentCategory) {
        Util.scrollToTop();
      }

      if (this.loadingCards === false) {
        if (category == "search") {
          this.cardSearch();
        } else {
          this.loadingCards = true;
          ApiCalls.loadCardsFromCategory(
            this,
            category,
            resp => {
              let cards = resp.data.resp.api_data.cards;
              parseCards(cards).forEach(c => {
                self.cardsCache[category].push(c);
              });

              self.previousCategory = self.currentCategory;
              self.currentCategory = category;
              self.loadingCards = false;
            },
            (error, context) => {
              console.log(error);
              self.loadingCards = false;
            },
            this.userId
          );
        }
      }
    },```

You'll want to pay attention to the line where I say ```self.cardsCache[category].push(c)```


4
  • 1
    Check out vues dynamic component, you can conditionally render a component with the is prop. Commented Oct 19, 2019 at 17:02
  • Thanks I'll take a look Commented Oct 19, 2019 at 17:16
  • I don't think that would solve my problem Commented Oct 19, 2019 at 17:24
  • The issue isn't getting vuejs to properly see when currentCategory changes, the issue is getting vuejs to properly watch and render newly added and or modified lists. Commented Oct 19, 2019 at 17:25

2 Answers 2

2

There are several ways to solve your problem. One of them may be use of computed properties:

{
  data() {
    return { 
      currentCategory: 'animals',
      cardsCache: {},
    };
  },
  computed: {
    currentCards: function () {
      return this.cardsCache[this.currentCategory];
    }
  },
  ...
}

The problem also may be caused by improper use of :key attribute in your v-for - it should be number or a string, not an object - something like card.id.

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

7 Comments

Thanks I'll take a look into the key, I did try the computed property but it had the same issue.
That didn't seem to change anything sadly.
Ya I used card.id as the key, which should be unique. However I suppose various lists being rendered may contain some of the same cards and therefore some of the same ids, but I don't think that would matter.
So may be the problem is not in your Vue code, but in the way you populate your cardsCache
I mean I can see plenty of data going into the cache when I do a console log and I'm not getting console errors. Do you think this isn't the proper way to render in vue ?
|
0

Adding in self.$forceUpdate() to the part after I loaded more data into the cache this forced vue to rerender the lists which fixed the problem.

1 Comment

This isn't really a solution to the underlying problem, you're just papering over the cracks and they'll come back to cause more problems down the line. I suspect the real problem is simply that you're falling foul of one of the reactivity caveats, vuejs.org/v2/guide/list.html#Object-Change-Detection-Caveats. For the code provided I would guess that self.cardsCache[category] = [] needs changing to self.$set(self.cardsCache, category, []). That should keep everything reactive and Vue will automatically do the rendering update.

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.