How to access / update variables inside v-for loop after mounted

Viewed 787

Below is my sample code. The value of Ending Inventory is calculated as endingInventory = beginningInventory + newInventory - totalSold. How can i access the value property of endingInventory and update it?

Any help is appreciated.

PS: I am new to Javascript & Vuejs. This could be a simple solution i am not aware of. my apologies in advance.

<template>
  <div class="row">
    <div class="col-md-6 col-xl-3" v-for="item in totals" :key="item.name">
      <p>{{ item.name }}:{{ item.value }}</p>
    </div>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        totals: [
          { name: 'Beginning Inventory', endPoint: 'beginning-inventory', value: 0 },
          { name: 'New Inventory', endPoint: 'total-new', value: 0 },
          { name: 'Total Sold', endPoint: 'total-sales', value: 0 },
          { name: 'Ending Inventory', endPoint: '', value: 0 }
        ]
      }
    },
    mounted() {
      this.getData(this.totals)
    },
    methods: {
      getData(totals) {
        // method to get data from server
        var http = this.$http
        totals.forEach(function (item) {

          if (item.endPoint) {
            var url = `http://localhost:3000/api/entity/${item.endPoint}`
            http.get(url)
            .then(response => {
              return response.body
            })
            .then(data => {
              item.value = data
            })
            .catch(error => {
              console.log(error)
              item.value =  0
            })
          } 
        })
      }
    }
  }
</script>
1 Answers

This should solve your problem with it not re-rendering, as well as helping you clean up some of your code to make it easier to understand.

export default {
  data() {
    return {
      totals: [
        { name: 'Beginning Inventory', endPoint: 'beginning-inventory', value: 0 },
        { name: 'New Inventory', endPoint: 'total-new', value: 0 },
        { name: 'Total Sold', endPoint: 'total-sales', value: 0 },
        { name: 'Ending Inventory', endPoint: '', value: 0 }
      ]
    }
  },
  mounted() {
    this.getData()
  },
  methods: {
    callApis() {
      // Define the base URL that will be used below to reduce the amount of code we are writing.
      const baseUrl = 'http://localhost:3000/api/entity';
    
      // This returns an array of Promise responses.
      return this.totals.map(({endPoint}) => 
        this.$http.get(`${baseUrl}/${endPoint}`)
      );
    },
    getData() {
      this.callApis()
        // "data" comes back destructured from the normal "response"
        .then((responses) => {
          // Vue.js requires that an Array or Object be completely changed at the root in order to trigger a re-render properly, which is why we are using a .map() here.
          this.totals = this.totals.map((total, idx) => {
            // This allows us to create a new object with the original properties from the total, while also allowing us to "overwrite" the "value" property we are getting back from the API call.
            return Object.assign({}, total, {
              value: responses[idx].data
            });
          });
        })
        .catch((err) => {
          // Do something here to handle the error.
        });
        
      // Your attempt...
      
      // method to get data from server
      /*var http = this.$http
      totals.forEach(function (item) {

        if (item.endPoint) {
          var url = `http://localhost:3000/api/entity/${item.endPoint}`
          http.get(url)
          .then(response => {
            return response.body
          })
          .then(data => {
            item.value = data
          })
          .catch(error => {
            console.log(error)
            item.value =  0
          })
        } 
      })*/
    }
  }
}
<template>
  <div class="row">
    <div class="col-md-6 col-xl-3" v-for="item in totals" :key="item.name">
      <p>{{ item.name }}:{{ item.value }}</p>
    </div>
  </div>
</template>

Related