1

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!

YJay
  • 91
  • 1
  • 12
  • Just to clarify, the 1st request gives you a list of users with their IDs, the 2nd is for the details of a specific user, and the 3rd is for a specific user's 'performance details'? Why doesn't the 1st request return the User's performance ID? – Sensanaty Aug 24 '20 at 16:36
  • Yes exactly! The last gives all the measurements and I need performance Id to get them. I wish it did, I'm using an api though and this is how it was given to me. – YJay Aug 24 '20 at 16:46

1 Answers1

1

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>
Sensanaty
  • 894
  • 1
  • 12
  • 35
  • Thanks so much, this works great! But how can I show the specific details? Like if I get back data [{ key: "temp" data: "38", },{"key": "vol", "data": "22"}]I want to show 38 in the Temperature box and 22 in Volume for whichever user returned that data. Otherwise if user didn't return data I just want an empty box. – YJay Aug 24 '20 at 17:15
  • Well, the same way you're displaying your User's names. Save the performance data into your `profiles` Object, and just refer to each key as needed. If you'd like to show the `performance-wrapper` div just with empty details, let me know and I'll modify my answer – Sensanaty Aug 24 '20 at 17:22
  • Thanks so much!! Yes I want it empty if there is no data, thanks so much for adding it! – YJay Aug 24 '20 at 19:01
  • Also for saving the performance data in profiles, does it make a difference that profiles is in vuex? – YJay Aug 24 '20 at 19:05
  • Even better if it's in a Vuex store, you can just save it from wherever you want in that case and access the store whenever you need the performance details as well. Performance will be better long term, since there's going to be less API calls – Sensanaty Aug 24 '20 at 19:20
  • Thank you! I got the data saved in profiles so now I have 2 more objects that contain the data, I'm a bit stuck on how I can show that data to the proper users, like for example lets say I have 3 objects of profile details and 2 of measurement data, how can I show the measurement data with performance ID 2 to profile ID 3? Is that connected to calling the keys? – YJay Aug 24 '20 at 19:44
  • @YJay That heavily depends on how your authentication currently works, and how you're saving user details. A general rule of thumb is to create a store entry with all the details of the currently logged in user. When you fetch their data, you save everything about them in the store then you just keep referencing the store whenever you need access to a specific user. Here's a forum post I recommend to junior devs often when it comes to Vue authentication https://laracasts.com/discuss/channels/vue/how-do-i-handle-loginregistration-and-sessions-with-vue-router-and-axios-for-an-spa – Sensanaty Aug 25 '20 at 09:21