YJay
YJay

Reputation: 91

Vue make axios GET and display data from array using key value?

I have a user profile card that displays different measurements in boxes, such as temperature, volume and weight.

Currently I'm getting the name of each user from an axios GET request, I need to then take the ID in that data and perform another GET request with the ID which gives me a performance data, in that data I am given a performance ID which I need to use to GET a final array of measurement data.

I'm wondering how I can make the last GET request only for users that have a performance Id and then take that data of the measurements and display in each user profile{that has measurement data) for each measurement box?

It looks something like this:

  1. I make the first axios request in vuex and use v-for to display each user name: GET api/profiles which returns:
"data": [
        {
            "id": 1,
            "name": "Joe",
        },
        {
            "id": 2,
            "name": "Max",
        },  
<div class="outer"  v-for="(item, index) in profiles" :key="item.id" >
 <p> User Name: {{ item.name }}</p> 
  1. I then need to make another GET request for performance: GET api/performance/{profileID} which returns only for users who have (other users return empty data object):
mounted() {
this.$store.state.profiles.forEach((item, index) => {
        axios.get('api/performance/' + this.profile[index].id)
            .then(response => {
            this.performanceId = response.data.data.id
          })
    });
}
 "data": {
        "id": 1,
        "profile_id": 2,
        .....other keys and values
      }
  1. and lastly for the users that have a performance ID I need to get the measurements: GET api/measurements/{profileID}/{performanceID} which returns:
"data": {
        "profileID": "2",
        "perfomanceID": "1",
        "data": [
            {
                "key": "temp",
                "data": "37",
            },
            {
                "key": "vol",
                "data": "22",
            },
            {
                "key": "weight",
                "data": "200",
            },

I would then like each data point to display in the box:

<div class="outer"  v-for="(item, index) in profiles" :key="item.id" >
    <p> User Name: {{ item.name }}</p> 
    <div class="box 1">Temperature: </div>
    <div class="box 2">Volume: </div>
    <div class="box 3">Weight: </div>
</div>

It would like this for Max's profile:
User Name: Max
  Temperature: 37
  Volume: 22
  Weight: 200

Any help would be appreciated, thanks!

Upvotes: 1

Views: 1464

Answers (1)

Sensanaty
Sensanaty

Reputation: 1106

If I understood you right, this is how I'd go about it.

Assuming there's no way to check whether a user has a performance ID other than making a request first, you can have a data() prop, for example hasPerformanceDetails which is set to false by default. Once you query the API for the performance ID, you can check whether it returned anything, and if it did just set hasPerformanceDetails to true. Then you just render the parts of the profile with the performance details using a v-if or v-show directive.

Something like this

data() {
  return { hasPerformanceDetails: false }
},
created() {
  this.populateProfile()
},
methods: {
  populateProfile() {
    // Call the measurements endpoint and check if response is empty or not
    if (apiResponse != null) {
      this.hasPerformanceDetails = true;
    }
  }
}

And in your <template>

<div class="outer" v-for="(item, index) in profiles" :key="item.id" >
  <p> User Name: {{ item.name }}</p>
  <div v-if="hasPerformanceDetails" class="performance-wrapper">
    <div class="box 1">Temperature: </div>
    <div class="box 2">Volume: </div>
    <div class="box 3">Weight: </div>
  </div>
</div>

Keep in mind it's the best to call the API on the created() hook, as this is before anything gets rendered or mounted into the DOM. See this answer for a reference. Vue will do the request, and only once all the data is there will it exit the created() hook and modify the items in data().

You can alternatively use v-show. v-if will straight up not render anything at all, v-show will have the section in the HTML but hide it using display: none

Alternatively, if you want the performance-wrapper div to always be there, but just empty, you can use a ternary operator instead

<div class="outer" v-for="(item, index) in profiles" :key="item.id" >
  <p> User Name: {{ item.name }}</p>
  <div class="box 1">Temperature: {{ hasPerformanceDetails ? item.temp : "Not available" }}</div>
  <div class="box 2">Volume: {{ hasPerformanceDetails ? item.volume : "Not available" }}</div>
  <div class="box 3">Weight: {{ hasPerformanceDetails ? item.weight : "Not available" }}</div>
</div>

Upvotes: 1

Related Questions