0
votes

In Vue, I'm inserting a value in a 2d array input field and calculating it per row, but the total value that is being returned only calculates the first row, and when I display, the computed value is all the same.

How can i calculate the inputted value so that the value will compute it per row and not just the first value?

<button @click="addFind">add</button>
<tr v-for="(classlist,index) in classlists" :key="'lab'+ classlist.id">
    <td>{{index +1}}</td>
    <td>{{classlist.student}}</td>
    <td v-for="(lab, i) in labs">
        <input v-model="lab.value[index]" />
    </td>
</tr>
    labs: [],
    classlists: [
      {  "student": "S1","id": 1 },
      {  "student": "S2","id": 2 },
      {  "student": "S3","id": 3 },
      {  "student": "S3","id": 4 },

    ],
  },
  methods: {
    addFind: function () {
      this.labs.push({ value: [] });
    }
  },
    computed: {
    studentTotalScores: function() {
      return this.labStudentScores.reduce(
        (acc, item) => acc + parseInt(item.value),
        0
      );
    }
    }

what i need:

NAME   | VALUE1 | VALUE2 | TOTAL   
name1  |   1    |   1    | 2
name2  |   2    |   3    | 5
name3  |        |        | 0

BUT THE OUTPUT:jsfiddle

NAME   | VALUE1 | VALUE2 | TOTAL   
name1  |   1    |   1    | 2
name2  |   2    |   3    | 2
name3  |        |        | 2
1

1 Answers

0
votes

A computed property can only have a single value, you can't calculate it 'per row'.

What you can do is have the value be an array, with one entry per row.

The data structure you're working with is a bit of a pain as the arrays are transposed relative to the table. Still, it can be done with a bit of fighting.

First, in the template you'd add a suitable <td> to the end of the rows:

<tr v-for="(classlist, index) in classlists" :key="'lab' + classlist.id">
  ... other tds not shown ...
  <td>
    {{ studentTotalScores[index] }}
  </td>
</tr>

Then studentTotalScores would be:

studentTotalScores: function() {
  return this.classlists.map((c, index) => {
    return this.labs.reduce((acc, item) => {
      const value = parseInt(item.value[index], 10) || 0
      return acc + value
    }, 0)
  })
}

I've added a base of 10 to parseInt to ensure consistent parsing, as well as || 0 so that NaN will be treated as 0.