0

I am building up a vue.js application for Shopify's JavaScript Buy SDK, but i am having problems with one variable not being updated.

Basically the shopClient variable is updated, but the shopCart stays null for some reason.

var vueApp = new Vue({
    el: '#shopify-app',
    created: function() {
        this.setupShopAndCart();
    },
    data: {
        shopCart: null,
        shopClient: null,
    },
    methods: {
        setupShopAndCart: function() {
            this.shopClient = ShopifyBuy.buildClient({
                apiKey: 'xxx',
                domain: 'xxx.myshopify.com',
                appId: '6'
            });
            if(localStorage.getItem('lastCartId')) {
              this.shopClient.fetchCart(localStorage.getItem('lastCartId')).then(function(remoteCart) {
                this.shopCart = remoteCart;
                cartLineItemCount = this.shopCart.lineItems.length;
                console.log(this.shopCart.checkoutUrl);
                console.log("fetching");
              });
            } else {
              this.shopClient.createCart().then(function (newCart) {
                this.shopCart = newCart;
                localStorage.setItem('lastCartId', this.shopCart.id);
                cartLineItemCount = 0;
                console.log(this.shopCart.checkoutUrl);
                console.log("failing");
              });
            }
        }, //setupShop end
    }
});
JavaCake
  • 3,845
  • 10
  • 53
  • 115

1 Answers1

3

You have a problem with scoping. this in the promise isn't the vue instance.

try this

var vueApp = new Vue({
    el: '#shopify-app',
    created: function() {
        this.setupShopAndCart();
    },
    data: {
        shopCart: null,
        shopClient: null,
    },
    methods: {
        setupShopAndCart: function() {
            var self = this;
            this.shopClient = ShopifyBuy.buildClient(
                {
                    apiKey: 'xxx',
                    domain: 'xxx.myshopify.com',
                    appId: '6'
                }
            );
            if(localStorage.getItem('lastCartId')) {
                this.shopClient.fetchCart(localStorage.getItem('lastCartId')).then(
                    function(remoteCart) {
                        self.shopCart = remoteCart;
                        cartLineItemCount = self.shopCart.lineItems.length;
                        console.log(self.shopCart.checkoutUrl);
                        console.log("fetching");
                    }
                );
            } else {
                this.shopClient.createCart().then(
                    function (newCart) {
                        self.shopCart = newCart;
                        localStorage.setItem('lastCartId', self.shopCart.id);
                        cartLineItemCount = 0;
                        console.log(self.shopCart.checkoutUrl);
                        console.log("failing");
                    }
                );
            }
        }, //setupShop end
    }
});

That stores the local vue instance in the self variable that is accessable to the promises allowing you to set the shopCart variable.

EDIT: As indicated lambda functions are correct if using ES2015 or newer

var vueApp = new Vue({
    el: '#shopify-app',
    created: function() {
        this.setupShopAndCart();
    },
    data: {
        shopCart: null,
        shopClient: null,
    },
    methods: {
        setupShopAndCart: function() {
            this.shopClient = ShopifyBuy.buildClient(
                {
                    apiKey: 'xxx',
                    domain: 'xxx.myshopify.com',
                    appId: '6'
                }
            );
            if(localStorage.getItem('lastCartId')) {
                this.shopClient.fetchCart(localStorage.getItem('lastCartId')).then(
                    (remoteCart) => {
                        this.shopCart = remoteCart;
                        cartLineItemCount = this.shopCart.lineItems.length;
                        console.log(this.shopCart.checkoutUrl);
                        console.log("fetching");
                    }
                );
            } else {
                this.shopClient.createCart().then(
                    (newCart) => {
                        this.shopCart = newCart;
                        localStorage.setItem('lastCartId', this.shopCart.id);
                        cartLineItemCount = 0;
                        console.log(this.shopCart.checkoutUrl);
                        console.log("failing");
                    }
                );
            }
        }, //setupShop end
    }
});
Justin MacArthur
  • 3,666
  • 17
  • 26
  • 1
    I think this is the correct answer. But you can enhance it by using **arrow function expression**, instead of storing `this` in a local variable. – Mani Oct 17 '16 at 16:18
  • Detailed discussion on the arrow function: http://stackoverflow.com/questions/22939130/when-should-i-use-arrow-functions-in-ecmascript-6 – Mani Oct 17 '16 at 16:20
  • 1
    I agree, if they are using ES 2015 or newer lamda functions are the better option for continuing scope. – Justin MacArthur Oct 17 '16 at 16:34