I've come across a problem. I'm trying to code a shopping cart. I have 4 components:
- LivingRoom.vue (where all products from Product are displayed)
- Product.vue (template with name, description and price for each product),
- ProductDetails.vue (details for each product)
- ShoppingCart.vue.
Each product in ProductDetails has button with addToCart
function, which takes as an argument item prop. Every time I try to add a new product (object) to the array, the previous one is probably replaced by the new one. I make a deep copy of each object by using Vue.util.extend
, so that quantity property is updated. And this works fine. But when I try to add different item to the cart array, the previous item disappears and the new one shows. I'm using EventBus and cart is emitted from the ProductDetails component to the ShoppingCart Component.
I helped myself by using this codepen: https://codepen.io/anon/pen/BEEwqd There everything works fine.
I'm fetching the data from local (static/products.json).
I tried to import project from github to codesandbox in order to make everything easier for you, but somehow it doesn't work as expected, therefore I'm pasting a link to my repo:
https://github.com/rafalpyska/weeklywebdevchallange10
LivingRoom.vue
<template lang="html">
<div class="container">
<transition-group tag="section" class="products" name="list">
<Product
v-for="item in dataToDisplay"
:item="item"
:key="item.id"
@click.native="handleProductDetails(item)"
/>
</transition-group>
</main>
<ProductDetails
v-if="isProductDetailsOpen"
:item="itemDetails"
:data="data"
/>
</template>
<script>
const API = '/static/products.json';
export default {
name: 'LivingRoom',
data() {
return {
status: true,
data: [],
dataToDisplay: [],
itemDetails: null,
}
},
components: {
Product,
ProductDetails
},
created() {
axios.get(API)
.then((response) => {
this.data = response.data[0].category[0];
for (let key in this.data) {
if (!this.data.hasOwnProperty(key)) continue;
this.dataToDisplay = this.data[key];
}
this.status = false;
})
},
methods: {
handleProductDetails(item) {
this.isProductDetailsOpen = true;
this.itemDetails = item;
}
}
Product.vue
<template lang="html">
<div>
<p>class="products__name">{{ name }}</p>
<p class="products__description">{{ description)</p>
<p class="products__price">${{ price }}</p>
</div>
</template>
<script>
export default {
name: "Product",
props: {
item: {
required: true
}
},
data() {
return {
name: this.item.title,
description: this.item.description,
price: this.item.price,
}
}
};
</script>
ProductDetails.vue
<template lang="html">
<section class="product-details">
<h2 class="product__name">{{ name }}</h2>
<label for="quantity">Quantity</label>
<input class="input__quantity" id="quantity" max="10" min="1" name="quantity" type="number"
v-model.number="item.quantity">
<button @click="addToCart(item)" class="btn">Add to cart</button>
</section>
</template>
<script>
import Vue from 'vue'
import {EventBus} from "@/event-bus.js";
export default {
name: "ProductDetails",
props: {
item: {
type: Object,
required: true
},
data: {
type: Object,
required: true
}
},
data() {
return {
cart: [],
name: this.item.title,
id: this.item.id,
quantity: this.item.quantity
}
},
methods: {
addToCart(productToAdd) {
let found = false;
this.cart.forEach((item) => {
if (item.id === productToAdd.id) {
found = true;
item.quantity += productToAdd.quantity;
}
});
if (found === false) {
this.cart.push(Vue.util.extend({}, productToAdd));
}
productToAdd.quantity = 1;
EventBus.$emit('update-cart', this.cart);
}
}
};
</script>
ShoppingCart.vue
<template lang="html">
<div class="cart" v-for="item in cart">
<div class="cart__product-info">
<p></p>
<p class="item__title">Product: {{ item.title }}</p>
<p class="item__quantity">Quantity: {{ item.quantity }}</p>
</div>
</div>
</div>
</section>
</template>
<script>
import {EventBus} from "@/event-bus.js";
export default {
name: "ShoppingCart",
data() {
return {
cart: null
}
},
created() {
EventBus.$on('update-cart', (item) => {
this.cart = item;
});
}
}
products.json
[
{
"category": {
"0": {
"title": "Living Room",
"id": 1
"products": {
"0": {
"title": "Red Seat",
"id": 1,
"description": "Armless Task Chair with Adjustable Height and Swivel Functionality. Comfortable 2 inches thick cushioned back and seat. 360 degrees swivel functionality. Pneumatic seat height adjustment. Upholstered in an easy to clean fabric. Dual wheel caster for any type of flooring",
"price": "45",
"image": "images/redseat.png",
"quantity": 1
},
"1": {
"title": "White Table",
"id": 2,
"description": "International Concepts Solid Wood Dining Table with Shaker Legs",
"price": "350",
"image": "images/whitetable.png",
"quantity": 1
}
}
}
}
]