I have a table of colors. I want to combine the same colors into single field & also their sum of quantity will be shown in that row.
For example, In the table below I have 2 "black" colors with quantities 5 & 2. Now want to combine this 2 rows into one & the quantity field will be "5 2 = 7" .
console.clear()
// New VueJS instance
var app = new Vue({
el: "#app",
data: {
colors: [{
"selectedColor": "white",
"selectedQty": 0,
"selectedUnit": "1",
}, {
"selectedColor": "black",
"selectedQty": "2",
"selectedUnit": "3",
},
{
"selectedColor": "black",
"selectedQty": 5,
"selectedUnit": "2",
},
{
"selectedColor": "red",
"selectedQty": 0,
"selectedUnit": "6",
}
]
},
methods: {
}
})
<!-- Include the library in the page -->
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<!-- App -->
<div id="app">
<table >
<thead>
<th >Color</th>
<th >Rate</th>
<th >Qty</th>
</thead>
<tbody v-for="(color, i) in colors" :key="i">
<td>
<input
type="text"
v-model="color.selectedColor"
>
</td>
<td >
<input
type="number"
v-model="color.selectedUnit"
/>
</td>
<td>
<input
type="number"
v-model="color.selectedQty"
/>
</td>
</tbody>
</table>
</div>
</div>
what I want is---
th{
border:1px solid black;
}
<table>
<thead>
<tr>
<th>Color</th>
<th>Rate</th>
<th>Qty</th>
</tr>
</thead>
<tbody>
<tr>
<td>white</td>
<td>1</td>
<td>0</td>
</tr>
<tr>
<td>Black</td>
<td>5</td>
<td>7</td>
</tr>
<tr>
<td>red</td>
<td>6</td>
<td>0</td>
</tr>
</tbody>
</table>
CodePudding user response:
You should create a computed method to create a new array, Instead of calling the data in your v-for
you can call the computed.
I did that in a codepen : https://codepen.io/ValentinM27/pen/GRGvmMp?editors=1011
Here is the main part of the code :
...
computed: {
getGrouped() {
let groupedColor = [];
this.colors.forEach((c, index) => {
// We check if the color has already been handle
const alreadyExist = groupedColor.some(existC => existC.selectedColor === c.selectedColor);
// If yes, we don't handle it again
if(alreadyExist) return;
this.colors.forEach((c2, index2) => {
// If it is the same color but not the actual index, we do the traitement
if(c.selectedColor === c2.selectedColor && index !== index2) {
c.selectedQty = parseInt(c.selectedQty) parseInt(c2.selectedQty);
c.selectedUnit = parseInt(c.selectedUnit) parseInt(c2.selectedUnit);
}
})
// We push the concatened color value
groupedColor.push(c);
})
// Our array with concatened values
return groupedColor;
}
},
...
And in your template
...
<tbody v-for="(color, i) in getGrouped" :key="i">
...
Hope it is what you are looking for
CodePudding user response:
You can accomplish it by a single pass using js reduce()
so need need to use multiple loops.
const data = { colors: [{ "selectedColor": "white", "selectedQty": 0, "selectedUnit": "1", }, { "selectedColor": "black", "selectedQty": "2", "selectedUnit": "3", }, { "selectedColor": "black", "selectedQty": 5, "selectedUnit": "2", }, { "selectedColor": "red", "selectedQty": 0, "selectedUnit": "6", } ]};
const result = data.colors.reduce((acc, { selectedColor: sc, selectedQty: sq, selectedUnit: su }) => ({...acc, [sc]: acc[sc] ? {selectedColor: sc, selectedQty: acc[sc].selectedQty parseInt(sq), selectedUnit: acc[sc].selectedUnit parseInt(su)} : {selectedColor: sc, selectedQty :parseInt(sq), selectedUnit: parseInt(su)}}), {});
console.log(Object.values(result));