0

I am using VUEJS to build a single page application. I have a single file component that gets some data from an API (using Axios) and uses v-for to render out a list like so:

<template>
  <div>
    <ul>
      <li v-for="division in divisions" :key="division.id_PK">
        {{ division.c6code }} - XXX
      </li>
    </ul>
  </div>
</template>

  props: {
    country: {
      type: Object,
      required: true
    }
  },
data() {
    return {
      divisions: [],
    },
methods: {
    async getDivisions() {
      const divisions = await APIService.getDivisions(
        this.country.igpeSID_FK
      )
      this.divisions = divisions
    },
}

An example of the API data source looks like /getDivisions/800001:

{
  "status": 200,
  "data": [
    {
      "id_PK": 205891,
      "igpeSID_FK": 800001,
      "c6code": "AB-CDE"
    },
    {
      "id_PK": 205890,
      "igpeSID_FK": 800001,
      "c6code": "FG-HIJ"
    },
    {
      "id_PK": 205889,
      "igpeSID_FK": 800001,
      "c6code": "KL-MNO"
    },
    {
      "id_PK": 205888,
      "igpeSID_FK": 800001,
      "c6code": "PQ-RST"
    },
    {
      "id_PK": 205887,
      "igpeSID_FK": 800001,
      "c6code": "WX-YZA"
    }
  ]
}

The rendered UI looks like so:

enter image description here

Now, there is another API endpoint that contains additional data that I need to put in place of the "XXX" placeholder shown above. That additional data source has a property called name and contains the actual division name which was not included in the /getDivisions API (only the associated property id_PK is provided).

Question: How can I get this name for each division?

An example of this endpoint that contains the additional data is: /getDivisionNameById/{id_PK} where id_PK is the parameter I need to pass to it from the getDivisions data shown above. So, for example, if I pass 205891 to the /getDivisionNameById/205891 I get back data that looks like so:

Example /getDivisionNamesById/205891:

{
  "status": 200,
  "data": [
    {
      "P_uniqueID": 16919,
      "isoGeoDivisionEntry_FK": 205891,
      "name": "ZABUL",
      "lang": "fa"
    },
    {
      "P_uniqueID": 16918,
      "isoGeoDivisionEntry_FK": 205891,
      "name": "ZABUL",
      "lang": "ps"
    }
  ]
}

I am thinking that I need to create a function that somehow creates a new array of names that I could then loop through in yet another v-for in my original template like so:

<li v-for="division in divisions" :key="division.id_PK">
        {{ division.c6code }} - <span v-for="divName in divisionNames" :key="division.id_PK">{{divName.name}}</span>
      </li>

async getDivisionNameById(id_PK) {
    const name = await APIService.getDivisionNameById(id_PK)
    this.divNames.push(name)
    
}

Obviously, I don't know what I am doing there...

Codesandbox with data:

https://codesandbox.io/s/intelligent-wind-21w35?file=/src/getDivisionNamesById.json

3
  • 1
    replace the content inside the li with a component, i.e <division-info :pk="division.id_PK"/> then inside the component do another API query lookup, its not ideal to do a bunch of querys but at least if you abstract it will lazyload Commented Jul 27, 2021 at 21:00
  • Good reminder, thx Commented Jul 28, 2021 at 0:51
  • @LawrenceCherone: Thanks so much. This was the simple solution for me! Commented Jul 28, 2021 at 13:31

2 Answers 2

1

You have to query the data first before rendering the content. You could fetch all the data in onMounted hook.

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

1 Comment

Thanks, it was a partial solution to my issue.
1

Thats a good place for a computed property. Edit this example as needed depending on how you call your APIs.

You could call both API endpoints in the mounted lifecycle-hook of the component. Included this with a simple timeout to simulate the data coming in at different times.

About the secondary API call(s) where you get the name-data: As you've already said, loop through the IDs and make the API calls. In this case you'd need to wait for the result of your first API call and then use those ID's it returns to make the second API call(s). Maybe this will help you with the await/asyc/then stuff: How to use async/await in Vue.js?

<template>
  <div class="hello">
    <ul>
      <li v-for="(division, index) in fullList" :key="index">
        {{ division }}
      </li>
    </ul>
  </div>
</template>

<script>
import divisions from "@/getDivisionsEntries.json";
import divisionNames from "@/getDivisionNamesById.json";
export default {
  name: "DivisionsList",
  data() {
    return {
      divisions: divisions.data,
      divisionNames: null,
    };
  },
  mounted() {
    setTimeout(() => {
      this.divisions = divisions.data;
    }, 1000);
    setTimeout(() => {
      this.divisionNames = divisionNames.data;
    }, 3000);
  },
  computed: {
    fullList: function () {
      let combinedArr = [];
      for (var divi of this.divisions) {
        var divNameData = this.divisionNames?.find(
          (x) => x.isoGeoDivisionEntry_FK === divi.id_PK
        );
        if (divNameData !== undefined) {
          combinedArr.push(`${divi.c6code} - ${divNameData.name}`);
        }
      }
      return combinedArr;
    },
  },
};
</script>

2 Comments

Excellent. Let me review and get back to you!
Thank you so much for your help. I ended up using another method BUT your answer helped me better understand the problem!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.