I have a very strange problem in vue.js/axios.
Scenario 1 : clear my products variable BEFORE send an HTTP request (see “<<<<< SCENARIO 1” mark). Then set products variable with a new array. It works but we see a flicker (due to the HTTP request duration). So I decided to clear the products variable IN the request.
Scenario 2 : clear my products variable IN the HTTP request. (see “<<<<< SCENARIO 2” mark).
But I don’t know why in Scenario 2 : my products variable is modified but the View don’t change ! So my product variable has 3 products with related quantity. Then quantity of one product change so I clear the product variable and refresh with the HTTP request. All is the same but quantity of 1 product has changed. But the view don’t reflect this !
let Cart = { components: { Product }, data: function() { return { products: [] } }, template: "<div><h3>Cart:</h3>" + '<product @productChanged="updateProductsCart(product)"' + 'style="display: inline-block; max-width: 90px;" v-for="product in products"' + ':id="product.id" :name="product.name" :priceWithCurrency="product.priceWithCurrency"' + ':initQuantity="product.initQuantity" :picture="product.picture" :hasDeletedBtn="true"' + ':isProductRefreshAuto="false"></product>' + "</div>", methods: { getAllProducts: function () { let $this = this; $this.clearProductsList();<<<<< SCENARIO 1 tdtdapi.get( '/cart/products/me', configs ).then(function (response) { $this.clearProductsList();<<<<< SCENARIO 2 console.log("getAllProducts.then >") console.log(response) let products = []; for( let i = 0, l = response.data.length; i < l; i++ ){ let product = response.data[i], productToAdd = { "name": "Product ",//todo delete raw value "priceWithCurrency": 45 }; //todo: create a class Product for( let prop in product ){ if( prop === "product" ) productToAdd.id = product[prop]; if( prop === "name" ) productToAdd.name = product[prop]; if( prop === "quantity" ) productToAdd.initQuantity = product[prop]; // if( prop === "description" ) productToAdd.description = product[prop]; if( prop === "price" ) productToAdd.priceWithCurrency = product[prop]; if( prop === "picture" ) productToAdd.picture = product[prop]; } products.push(productToAdd); } $this.setProducts(products); }).catch(function (error) { console.log(error); }); }, updateProductsCart: function( product ) { console.log("updateProductsCart >") console.log(product) this.getAllProducts(); }, setProducts: function(products) { console.log("setProducts >") console.log(products) this.products = products; console.log(this.products) }, clearProductsList: function() { this.products.splice( 0, this.products.length ); } }, mounted() { this.getAllProducts(); }, computed: { } }; var app = new Vue({ el: "#app", components: { "ProductsList": ProductsList, "Cart": Cart } });
There is the Product component if that help :
let Product = { data() { return { quantity: this.initQuantity, price: this.getPriceWithoutSymbols() } }, props: { id: { type: Number, required: true }, name: { type: String, required: true }, description: { type: String, default: "" }, priceWithCurrency: { type: Number, required: true }, initQuantity: { type: Number, default: 0 }, picture: { type: String, default: "" }, hasDeletedBtn: { type: Boolean, default: false }, isProductRefreshAuto: { type: Boolean, default: true } }, template: '<article :id="id">' + '<div>{{ name }}</div>' + '<div>{{ description }}</div>' + '<div>{{ price }}</div>' + '<div><img :src="picture"/></div>' + '<div>Quantity: {{ quantity }}</div>' + '<div>Total for this product: {{ totalPrice }}</div>' + '<div>' + '<button @click="decrementQuantity" type="button">-</button>' + '<button @click="incrementQuantity" type="button">+</button>' + '<br /><button v-if="hasDeletedBtn" @click="deleteProductQuantity" type="button">Delete product</button>' + '</div>' + '</article>', methods: { addQuantity( valueToAdd ){ //if quantity 0 to 1 ==> post if( (this.quantity === 0) && (valueToAdd >= 1) ){ this.postProductQuantity(valueToAdd); } //if quantity 1 to 0 ==> delete else if( (this.quantity === 1) && (valueToAdd === -1) ){ this.deleteProductQuantity(); } //else ==> put else{ this.putProductQuantity(valueToAdd); } }, postProductQuantity(valueToAdd){ console.log("POST") let $this = this; tdtdapi.post( '/cart/products/me', querystring.stringify({ product: $this.id, quantity: valueToAdd }), configs ).then(function (response) { console.log(response); $this.setQuantity(response.data.quantity); }).catch(function (error) { console.log(error); }); }, putProductQuantity(valueToAdd){ console.log("PUT") let $this = this; tdtdapi.put( '/cart/products/me', querystring.stringify({ product: $this.id, quantity: ($this.quantity + valueToAdd) }), configs ).then(function (response) { console.log(response); $this.setQuantity(response.data.quantity); }).catch(function (error) { console.log(error); }); }, deleteProductQuantity(){ console.log("DELETE") let $this = this; tdtdapi.delete( '/cart/products/me/' + this.id, configs ).then(function (response) { console.log(response); $this.setQuantity(0);//todo: use v-show to hide product when (this.quantity === 0) }).catch(function (error) { console.log(error); }); }, emitChanged() { this.$emit( "productChanged" ); }, incrementQuantity(){ this.addQuantity(1); }, decrementQuantity( product ){ console.log(product) // if( this.quantity >= 1 ){ // this.addQuantity(-1); // } }, getPriceWithoutSymbols(){ //todo: if price contains currency, when need to get only the value return this.priceWithCurrency; }, setQuantity( quantity ){ if( this.isProductRefreshAuto ){ this.quantity = quantity; } this.emitChanged(); } }, computed: { totalPrice: function(){ return (this.quantity * this.price).toFixed(2); } } };
Advertisement
Answer
The problem is that we must refresh the data of Product with the props.
Basically when the parent (here the Cart component) change the quantity of Product with the props (here initQuantity), we must say to Product instance that he must change is data (here quantity) with his props (initQuantity).
So we must add a watch at the end of Product component :
computed: { ... }, watch: { initQuantity( newQuantity ){ this.quantity = newQuantity; } }
I found my answer here