[Vuejs]-Vue js issues recalling url from API

0đź‘Ť

âś…

This answer solves some problems after @chillin’s answer.

As I mentioned in the comments, the reason you’re not seeing any store urls is that you are iterating over an object that doesn’t exist:

The problem, (as @chillin saw) is that you are iterating through
game.store when you should be iterating through game.stores If you
inspect the game object, you’ll notice that there is a stores
array within, but not a store one.

You should also note that having the urls in anchors on their own will cause them to be squashed into one line. Wrapping the anchors in <p> elements solves that problem:

Before:

<a v-for="store in game.store" :href="store.url" :key="store.ID">{{store.url}}</a>

before

After:

<p v-for="store in game.stores" :key="store.ID">
    <a :href="store.url">{{store.url}}</a>
</p>

after

Also, I’m not sure if the stores array could ever have duplicate IDs, (maybe if multiple versions of the same game are in the same store), but if that ever does happen your code could crash. So it might be a better option to simply use the index of the object as it’s key, like so,

<p v-for="(store, index) in game.stores" :key="index">
    <a :href="store.url">{{store.url}}</a>
</p>

…so as to avoid this potential problem.

Here’s a demo and here’s the modified codepen (I also removed the computed property storeUrl, as it was unused.

0đź‘Ť

Updated with actual example

First, don’t join them in the computed, and then implement using a v-for, something like this should work.

Basically this is my own take of course, but based on the actual API data, something like this should work, with a loop in a loop, I map out the data just for ease of use, you will end up with something like:

[
   {
      key: 'gta-v',
      storeUrls: [
         {
            key: 'steam',
            url: 'http:// ...'
         },
         {
            key: 'riot',
            url: 'http:// ...'
         }
      ]
   },
   {
      key: 'fortnite',
      storeUrls: [
         {
            key: 'steam',
            url: 'http:// ...'
         },
         {
            key: 'riot',
            url: 'http:// ...'
         }
      ]
   }
]

Using this we can also double down on a v-for in the template, and sort your data by game, and for each game loop through it’s storeUrl’s for a nice clean list, this also utilises the use of actual keys, rather than index.

<template>
   <div class="root">
      <div class="game" v-for="game in games" :key="game.key">
         <h1>{{ game.key }}</h1>
         <a v-for="store in game.storeUrls" :href=“store.url” :key="store.key">
            {{store.url}}
         </a>
      </div>
   </div>
</template>

export default {
   data() {
      return {
         myData: null
      }
   },

   computed: {
      games() {
         if (!this.myData) return [];
         return this.myData.results.map(game => {
            key: game.slug,
            storeUrls: game.stores.map(store => {
               return {
                  key: store.store.slug,
                  url: store.url_en
               }
            });
         });
      }
   },

   methods: {
      getData() {
         // However you do it, but the base data, with no mapping.
         this.myData = axios.get('...'); 
      }
   }
}

0đź‘Ť

I’m new to Vue, so maybe someone else can provide a better answer. But seems right to use v-for to loop over your store URLs.


Assuming your gameId watcher is running and completing successfully, I don’t think you need to change anything since this.game.stores should already contain an array of objects.

So you should be able to do something like:

<a v-for="store in game.stores" :href="store.url" :key="store.store.id">{{ store.url }}</a>

I don’t know the difference between store.id and store.store.id, but I’ve assumed that store.store.id uniquely identifies a store and is okay to be used as the key. (You’d have to check the API documentation to see what the IDs represent.)

Leave a comment