0

My vue component to add to cart like this :

<template> 
    <div class="wrapper">
        ...
        <b-btn variant="warning" class="btn-square mt-2 col-md-12" @click="addToCart(item)"><i class="fa fa-cart-arrow-down"></i> Add to cart</b-btn>
        ...
    </div>
</template>
<script>
    export default {
        ...
        methods: {
            addToCart(item) {
                let data = [{
                    number: item.number,
                    price: item.price,
                    description: item.description,
                    quantity: this.quantity,
                }]
                if (this.$session.get(SessionKeys.Cart) === undefined || this.$session.get(SessionKeys.Cart) === null) {
                    this.$session.set(SessionKeys.Cart, data);
                }
                else {
                    let newData = this.$session.get(SessionKeys.Cart)
                    newData.push(data[0])
                    this.$session.set(SessionKeys.Cart, newData);
                }
            }
        }
    }
</script>

If click add to cart, it will save the data in the session storage

I have global.js and I set session storage there. It like this :

export const SessionKeys = {
    Cart: 'logCart'
};

And I have vue component header to display notification cart like this :

<template>
    <b-navbar-nav>
        <div class="d-md-down-none mr-2" @click="showCart = !showCart" v-show="!verified">
            <i class="icon-basket"></i>
            <b-badge pill variant="danger" class="ml-1">{{items.length}}</b-badge>
        </div>
        <div class="cart" v-show="showCart">
            <div v-show="items.length > 0" class="m-0 p-1 border ">
                <b-list-group>
                    <b-list-group-item v-for="item in items" transition="fade">
                        <b-row>
                            <b-col cols="2" class="m-0 p-0">
                                <b-img src="./img/products/test.jpg" height="50" />
                            </b-col>
                            <b-col class="p-0 pl-3">
                                <i class="fa fa-dropbox"></i><small><b>{{item.description }}</b></small><br/>
                                <small class="p-1"><i class="fa fa-check"></i> {{ item.quantity }} pcs x Rp. {{ item.price }}</small><br/>
                                <small class="p-1"><i class="fa fa-check"></i> Sub: Rp. {{item.quantity * item.price}}</small>
                                <i class="fa fa-trash text-danger float-right" @click="removeFromCart(item)"></i>
                            </b-col>
                        </b-row>
                    </b-list-group-item>
                    <b-list-group-item class="p-0 align-middle">
                        <div class="bg-secondary text-lg-center text-dark font-lg font-weight-bold">Rp. 123</div>
                    </b-list-group-item>
                </b-list-group>
                <b-btn class="btn-square col-md-12 mt-1" variant="warning" href="/#/orders/payment"><i class="fa fa-credit-card-alt"></i> Check out</b-btn>
            </div>
            <div v-show="items.length === 0">
                <p>Your cart is empty!</p>
            </div>
        </div>
    </b-navbar-nav>
</template>

<script>
    export default {
        name: "cartDropdown",
        data() {
            return{
                items: this.$session.get(SessionKeys.Cart) ? this.$session.get(SessionKeys.Cart) : [],
                showCart: false,
                verified: false
            }
        }
    }
</script>

If I click add to cart, the notification in the header is not update automatic. I must refresh the page first

How can I make it automatic update when click add to cart?

Seems it will using watch, but i'm still confused to implement it

moses toh
  • 12,344
  • 71
  • 243
  • 443
  • it should be caused by reactivity issue (can't detect adding item to one array). so inside the function=`addToCart`, replace `let newData = this.$session.get(SessionKeys.Cart)` with `let newData = this.$session.get(SessionKeys.Cart).slice()`. then try again. – Sphinx Sep 12 '18 at 00:00
  • and in your cartDropDown component, you declare the data property=**items** with session data, but I didn't see any codes will sync it with latest value. For your case, it may be better add one prop like **cartItem** for **cartDropDown**, then parent component bind this props with the latest data of the shopping cart (the component with the method=addTocart seems one child component or declare in parent component) – Sphinx Sep 12 '18 at 00:08
  • @Sphinx I try your first comment. But it's the same. On the second comment, it can't be done because the two components are different. They don't have a parent and child relationship. So it can't send via prop – moses toh Sep 12 '18 at 06:39
  • 1
    If so, uses [event bus](https://stackoverflow.com/questions/42615445/vuejs-2-0-emit-event-from-grand-child-to-his-grand-parent-component/51661633#51661633) or [emit/on root](https://stackoverflow.com/a/51661633/5665870) to notify other component the data already change (then that component will read latest session data), or use [Vuex](https://vuex.vuejs.org/) instead of saving into session will be a better solution. – Sphinx Sep 12 '18 at 17:57
  • @Sphinx Okay thanks. I use `emit` and it works – moses toh Sep 13 '18 at 01:54

0 Answers0