I am learning Vue and I am making a shopping cart style table, I have the problem that when I INCREASE and DECREASE from the table the quantity does not increase or decrease in the visual part, but if I inspect the component and the data inside the array if the quantity is updated, I attach image.
I attach an image of how is the table, as you can see it is a simple common table of a shopping cart, I saw other tutorials or people who have done it but it still does not work, I do not know if I'm missing something else or I'm doing wrong the part of auto increase the amount of the row.
Attached is the script code and template
<table ref="table">
<thead>
<th
v-for="(head, key) in fields"
:key="key"
v-text="head"
></th>
</thead>
<tbody v-if="items.length > 0">
<tr v-for="(product, i) in items" :key="i">
<td v-text="product.code"></td>
<td v-text="product.name"></td>
<td>
${{ Number(product.price).toLocaleString() }}
</td>
<td width="200">
<!-- <b-form-input type="number" min="0" size="sm" :value="product.stock" @change="changeStock(i)"></b-form-input> -->
<a
@click="decrement(i)"
v-bind:disabled="product.count <= 1"
>-</a
><!-- v-bind:disabled="product.count<=1" -->
{{ product.count }}
<a
@click="increment(i)"
> </a
>
</td>
<td width="200">
<b-input-group>
<b-form-input
type="number"
min="0.00"
size="sm"
value="0"
></b-form-input>
<b-input-group-append>
<b-input-group-text>
%
</b-input-group-text>
</b-input-group-append>
</b-input-group>
</td>
<td>${{ sumTotalproduct(product.price) }}</td>
<td width="10">
<a
href="#"
v-b-tooltip.hover
title="Quitar de la cotización"
@click="deleteItem(i)"
><i
></i
></a>
</td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td>NETO</td>
<td colspan="2">
${{ Number(totalNeto).toLocaleString() }}
</td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td>IVA (19%)</td>
<td colspan="2">
${{ Number(totalIVA).toLocaleString() }}
</td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td>TOTAL</td>
<td colspan="2">
${{ Number(total).toLocaleString() }}
</td>
</tr>
</tbody>
</table>
export default {
name: 'Quote',
data () {
return {
fields: [
'Código',
'Producto',
'Precio',
'Cantidad',
'Descuento',
'Total',
'Acción'
],
items: [],
hover: true,
dark: false,
noCollapse: true,
headVariant: null,
tableVariant: '',
productSelected: null,
options: [],
chooseProduct: null,
products: []
}
},
created () {
this.getProducts()
},
computed: {
totalNeto: function () {
var sum = 0
this.items.forEach(e => {
sum = e.price
})
return sum
},
totalIVA: function () {
return parseInt(this.totalNeto * 0.19)
},
total: function () {
return this.totalNeto this.totalIVA
},
},
methods: {
openSideBarModal () {
this.$root.$emit('bv::toggle::collapse', 'my-sidebar')
},
getProducts () {
axios.get(route('products.listAll')).then(res => {
this.options = res.data.data
})
},
currentDataItems () {
var stock = 1
// Obtenemos los datos del producto.
var data = this.options.find(p => p.id == this.chooseProduct.id)
// Validamos que no exista el dato ya en la tabla.
if (this.items.length > 0) {
var existData = this.items.some(d => d.id == data.id)
if (!existData) {
data.count = 1 //data.stock stock
this.items.push(data)
// }else{
// data.stock = data.stock stock
}
return
}
data.count = 1
this.items.push(data)
console.log(this.items)
},
sumTotalproduct (price) {
return Number(price).toLocaleString()
},
increment (i) {
this.items[i].count
},
decrement (i) {
if (this.items[i].count == 0) return
this.items[i].count--
},
deleteItem (index) {
Swal.fire({
title: '¿Estas seguro de quitar el producto?',
text:
'Recuerda, que puedes volver a añadir al carro el producto.',
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#283669',
cancelButtonColor: '#d33',
confirmButtonText: 'Si, quitar!'
}).then(result => {
if (result.isConfirmed) {
this.items.splice(index, 1)
Swal.fire(
'Eliminado!',
'El producto se a elimina de la cotización.',
'success'
)
}
})
}
}
}
CodePudding user response:
I am not sure what issue you are facing but it is working fine for me. I juts created a working code snippet. Please have a look and let me know if any further changes required in that.
new Vue({
el: '#app',
data: {
items: [{
count: 0
}, {
count: 0
}, {
count: 0
}, {
count: 0
}, {
count: 0
}]
},
methods: {
increment (i) {
this.items[i].count
},
decrement (i) {
if (this.items[i].count == 0) return
this.items[i].count--
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div v-for="(product, i) in items" :key="i">
<button @click="decrement(i)"
v-bind:disabled="product.count <= 1">-</button>
{{ product.count }}
<button @click="increment(i)"> </button>
</div>
</div>
CodePudding user response:
Try this...
increment (i) {
this.$set(this.items[i], 'count', this.items[i].count 1)
},
decrement (i) {
if (this.items[i].count == 0) return
this.$set(this.items[i], 'count', this.items[i].count - 1)
}
CodePudding user response:
The issue here likely has to do with Vue 2's reactivity system. When you change a member of an object or array, Vue only knows to watch for and react to it if it is defined in the vue object or if you tell it to by using Vue.set(). if you change your code to this it should work.
increment(i) {
this.$set(this.items[i], count, this.items[i] 1);
},
decrement(i) {
if (!this.items[i].count) return;
this.$set(this.items[i], count, this.items[i] - 1);
}
Rohìt's answer worked because he defined all the objects in the data function.