Javier Martin
Javier Martin

Reputation: 67

How to calculate partial value and total value in Vue.js?

I'm starting with Vue.js and I don't know how can I calculate the partial value and total value inside a v-for display.

I'm getting some info from a JSON with the next structure:

[saldos]
  [bank]
    [data]
      [account]
        - name
        - balance
      [account]
        - name
        - balance
    [meta]
      - info
  [bank]
    [data]
      [account]
        - name
        - balance
      [account]
        - name
        - balance
    [meta]
      - info

Each bank could be 0 accounts, 1 account or more accounts.

I need to get the partial value of each bank (it is the sum of all accounts 'balance' inside the same bank) and the total value (it is the sum of all partial values previously calculated for each bank)

My Vue.js file is:

var saldo = new Vue({
    el: "#listasaldos",
    data: {
        saldos:[],
    },
    created: function(){
        console.log("Cargando ...");
        this.get_saldos();
    },

    methods:{
        get_saldos: function(){
            fetch("./api.php?action=saldosapi")
            .then(response=>response.json())
            .then(json=>{this.saldos=json.saldos})
        }
    }
});

And my HTML file is:

<div id="listasaldos">
    <h1>Title</h1>
    <h2>{{totalValue}}</h2>

    <div v-for="bank in saldos">

      <h3>{{partialValue}}</h3>

      <table>
      <thead>
        <tr>
          <th>Name</th>
          <th>Balance</th>
        </tr>
      </thead>
      <tbody v-for="account in bank.data">
        <tr> {{account.name}}</tr>
        <tr> {{account.balance}}</tr>
      </tbody>
      </table>

    </div>
</div>

How can I do it?

Thanks!

Upvotes: 2

Views: 351

Answers (1)

adiga
adiga

Reputation: 35222

For the saldos total, you could add a computed property and use reduce to calculate the total:

computed: {
    totalValue() {
      return this.saldos.map(({data}) => data).flat().reduce((a, b) => a + b.balance, 0);
    }
}

I'm not familiar with how one would go about adding vue computed properties inside a loop. According to this answer you either have to create a component for each bank or add a function called getBankTotal inside methods:

getBankTotal: function(bank){
   return bank.data.reduce((a, b) => a + b.balance, 0)
}

And use it in your HTML:

<h3>{{getBankTotal(bank)}}</h3>

Here's a working snippet: (I have not used vue before. So, correct me if any syntax or pattern is wrong)

var saldo = new Vue({
  el: "#listasaldos",
  data: {
    saldos: [],
  },
  created: function() {
    this.get_saldos();
  },
  methods: {
    getBankTotal: function(bank) {
      return bank.data.reduce((a, b) => a + b.balance, 0)
    },
    get_saldos: function() {
      this.saldos = [{
        data: [{
          name: "a/c 1",
          balance: 100
        }]
      }, {
        data: [{
          name: "a/c 2",
          balance: 300
        }, {
          name: "a/c 3",
          balance: 400
        }]
      }]
    }
  },
  computed: {
    totalValue() {
      return this.saldos.map(({data}) => data).flat().reduce((a, b) => a + b.balance, 0);
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="listasaldos">
  <h1>Title</h1>
  <h2>Total Value: {{totalValue}}</h2>

  <div v-for="bank in saldos">

    <h3>Partial Value: {{getBankTotal(bank)}}</h3>
    <table>
      <thead>
        <tr>
          <th>Name</th>
          <th>Balance</th>
        </tr>
      </thead>

      <tbody>
        <tr v-for="account in bank.data">
          <td>{{account.name}}</td>
          <td>{{account.balance}}</td>
        </tr>
      </tbody>
    </table>
    <hr>
  </div>
</div>

Upvotes: 3

Related Questions