0
votes

i am using a v-for to display list of product from an api request, the product card contains three buttons, one of the Adds item to cart,with a shopping-cart icon.

i want it so that when a user clicks the add to cart button, the shopping-cart icon changes to a spinner icon

I try declaring a "loading" in the data object, default set to false, so in my add to cart function, before the function is called, loading is set to true,

And in my template i use a v-show="loading" which set the visibility of the fa-spin to true if loading is true

//template

 <template>
<div class="row">
        <div v-for="product in products" v-bind:key="product_slug"
             class="col-md-auto mx-auto card text-center card-product">
            <div class="card-product__img">
                <img class="card-img" src="img/product/product1.png" alt="">
                <ul class="card-product__imgOverlay">
                    <li>
                        <button><i class="ti-search"></i></button>
                    </li>
                    <li>
                        <button @click="addToCart(product.id, product.slug, product.price)"><i
                                class="ti-shopping-cart"></i> <i v-show="loading" class="fa fa-spinner fa-spin"></i>
                        </button>
                    </li>
                    <li>
                        <button><i class="ti-heart"></i></button>
                    </li>

                </ul>
            </div>
            <div class="card-body">
                <p>Accessories</p>
                <h4 class="card-product__title"><a href="single-product.html">{{ product.slug }}</a></h4>
                <p class="card-product__price">₦ {{ product.price}}</p>
            </div>
        </div>





//script

<script>
    export default {
        data() {
            return {
                loading: false,
                products: [],
                product: {
                    "id": '',
                    "slug": '',
                    "product_image_1": '',
                    "product_image_2": '',
                    "product_image_3": '',
                    "product_image_4": '',
                    "price": '',
                    "qty": '',
                    "stock_status": '',
                    "sku": '',
                    "short_description": '',
                    "description": '',
                },
                product_slug: '',
                pagination: {},
            }
        },
        created() {

            this.fetchProduct();
        },
        methods: {
            fetchProduct(page_url) {

                //assign variable to this

                let vm = this;

                // check if page url exist, = page url else = /api/shop

                page_url = page_url || '/api/shop';

                fetch(page_url)
                    .then(res => res.json())
                    .then(res => {
                        this.products = res.data;
                        vm.makePagination(res.links, res.meta);

                    })
                    .catch(err => console.log(err));
            },

            makePagination(links, meta) {
                //Make an object made up of  meta, page details from the api response

                let pagination = {
                    current_page: meta.current_page,
                    last_page: meta.last_page,
                    next_page_url: links.next,
                    prev_page_url: links.prev,
                };

                // Set the object to the pagination value

                this.pagination = pagination;

            },
            addToCart(id, slug, price) {

                this.loading = true;
                axios.post('/api/cart', {
                    id: id,
                    name: slug,
                    price: price,
                })
                    .then(function (response) {
                        this.loading = false;
                        console.log(response.data);

                    })
                    .catch(function (err) {
                        this.loading = false;
                        this.addToCart = err;
                    });
            }
        }
    }
</script>

The problems are 1) Once the add to cart button is clicked, the spinner shows in all of the product's card. 2) fa-cart icon is not hiding, shows side-by-side with the shopping-cart icon 3) fa-spin continues, even after success of api request

1

1 Answers

0
votes

You need to maintain a dictionary of the loading state. In addToCart function, you need to set true for particular product id. Try this code.

addToCart(id, slug, price) {

                this.loading[id] = true;
                axios.post('/api/cart', {
                    id: id,
                    name: slug,
                    price: price,
                })
                    .then(function (response) {
                        this.loading[id] = false;
                        console.log(response.data);

                    })
                    .catch(function (err) {
                        this.loading[id] = false;
                        this.addToCart = err;
                    });
            }

In Fetch product function made some changes.

fetchProduct(page_url) {

                //assign variable to this

                let vm = this;

                // check if page url exist, = page url else = /api/shop

                page_url = page_url || '/api/shop';

                fetch(page_url)
                    .then(res => res.json())
                    .then(res => {
                        this.products = res.data;
                        this.products.filter(function (item) {
                                  vm.loading[item.id]=false;
                                  return item;
                         })

                        vm.makePagination(res.links, res.meta);

                    })
                    .catch(err => console.log(err));
            },

html changes.

 <button @click="addToCart(product.id, product.slug, product.price)"><i
                                class="ti-shopping-cart"></i> <i v-show="loading[product.id]" class="fa fa-spinner fa-spin"></i>
                        </button>