0

I created my own angular directive which can simply be used as:

<basket-summary></basket-summary>

This element is used on my master template page (the index.html).

The directive is as follows:

/* Directive */
angular.module('ecommerceDirectives').directive('basketSummary', [function() {
    return {
        restrict : 'E',
        scope: {},
        replace: true,
        controller : 'BasketController',
        controllerAs: 'basketController',
        bindToController: {
            basketController : '='
        },
        templateUrl: function(element, attrs) {
            if (typeof attrs.templateUrl == 'undefined') {
                return 'app/views/basket-summary.html';
            } else {
                return attrs.templateUrl;
            }
        },
        link: function (scope, element, attrs) {
            console.log("test");
        }
    };
}]);

The templateUrl of this directive is as follows:

<div class="btn-group pull-right"> 
    <a class="btn btn-warning" ng-click="basketController.viewBasket()"><span class="badge">{{basketController.getTotalQuantities()}}</span> <span class="hidden-xs">Shopping</span> Cart</a>
    <button type="button" class="btn btn-warning dropdown-toggle" data-toggle="dropdown">
        <span class="fa fa-caret-down"></span>
        <span class="sr-only">Toggle Dropdown</span>
    </button>

    <div class="dropdown-menu">
        <div class="col-xs-12 cartItemHeader">
            <h4>My Shopping Cart</h4>
        </div>

        <div class="quickCart" ng-repeat="cartItem in basketController.customerBasket.items">
            <div class="col-xs-12 cartItemWrap">
                <div class="col-xs-12 desc"><a href="">{{cartItem.product.title}}</a></div>
                <div class="col-xs-5 col-sm-8 price">{{cartItem.product.rrp_currency}} {{cartItem.product.rrp_amount}}</div>
                <div class="col-xs-6 col-sm-3 units">Items: {{cartItem.quantity}}</div>
                <div class="col-xs-1 trash"><a ng-click="basketController.deleteCartItem(cartItem.product.id)"><i class="fa fa-trash"></i></a></div>
           </div>
       </div>
   </div>

And the BasketController is as follows:

/* Controller */
angular.module('ecommerceControllers').controller('BasketController', ['$rootScope', '$scope', '$route', '$location', 'CustomerBasketService', 'AppSettingService', 'StorageService', 'DEFAULT_CURRENCY_CODE', 'MERCHANT_ID_KEY', function($rootScope, $scope, $route, $location, CustomerBasketService, AppSettingService, StorageService, DEFAULT_CURRENCY_CODE, MERCHANT_ID_KEY) {

    function basketProduct(product) {
        this.id = product.id;
        this.title = product.title;
        this.categories = product.categories;
        this.images = product.imaes;
        this.created_on = product.created_on;
        this.sku_code = product.sku_code;
        this.lang = product.lang;
        this.short_description = product.short_description;
        this.attributes = product.attributes;
        this.rrp_currency = product.rrp_currency;
        this.rrp_amount = product.rrp_amount;
        this.barcode_number = product.barcode_number;
        this.last_modified_on = product.last_modified_on;
    }

    function basketItem(quantity, product) {
        this.quantity = quantity;
        this.product = new basketProduct(product);
    }

    function load() {
        var basket = StorageService.get("customer_basket");
        if (basket) {
            for (var i = 0; i < basket.items.length; i++) {
                var cartItem = basket.items[i];
                cartItem = new basketItem(cartItem.quantity, cartItem.product);
                basket.items[i] = cartItem;
            }
        }

        return basket;
    }

    var basketController = this;
    $scope.basketController = basketController;
    basketController.customerBasket = load();

    if (!basketController.customerBasket) {
        basketController.customerBasket = {
            shipping : null,
            taxRate : null,
            tax : null,
            items : []
        };
    }

    basketController.addCartItem = function(quantity, product) {
        if (product == undefined || product == null) {
            throw "No Product was specified.";
        }

        if (quantity == undefined || quantity == null) {
            quantity = null;
        }

        var found = false;
        if (basketController.customerBasket && basketController.customerBasket.items && basketController.customerBasket.items.length > 0) {
            for (var i = 0; i < basketController.customerBasket.items.length; i++) {
                var cartItem = basketController.customerBasket.items[i];
                if (product.id === cartItem.product.id) {
                    found = true;
                    cartItem.quantity = cartItem.quantity + quantity;
                    if (cartItem.quantity < 1) {
                        basketController.customerBasket.items.splice(i, 1);
                    } else {
                        $rootScope.$broadcast('customerBasketItemUpdated', {item: cartItem});
                    }
                }
            }
        }

        if (!found) {
            var cartItem = new basketItem(quantity, product);
            basketController.customerBasket.items.push(cartItem);
            $rootScope.$broadcast('customerBasketItemAdded', {item: cartItem});
        }

        basketController.saveBasket();
    }

    basketController.updateBasket = function() {
        if (basketController.customerBasket && basketController.customerBasket.items && basketController.customerBasket.items.length > 0) {
            for (var i = 0; i < basketController.customerBasket.items.length; i++) {
                var cartItem = basketController.customerBasket.items[i];
                if (cartItem.quantity < 1) {
                    basketController.customerBasket.items.splice(i, 1);
                }
            }
        }

        basketController.saveBasket();
    }

    basketController.deleteCartItem = function(productId) {
        if (productId == undefined) {
            throw "Product ID is required.";
        }

        if (basketController.customerBasket && basketController.customerBasket.items && basketController.customerBasket.items.length > 0) {
            for (var i = 0; i < basketController.customerBasket.items.length; i++) {
                var cartItem = basketController.customerBasket.items[i];
                if (productId == cartItem.product.id) {
                    basketController.customerBasket.items.splice(i, 1);
                }
            }
        }

        //Save
        basketController.saveBasket();
    }

    basketController.getCurrencyCode = function() {
        var code = DEFAULT_CURRENCY_CODE;

        if (basketController.customerBasket && basketController.customerBasket.items && basketController.customerBasket.items.length > 0) {
            code = basketController.customerBasket.items[0].product.rrp_currency;
        }

        return code;
    };

    basketController.getTotalQuantities = function(id) {
        var total = 0;
        if (basketController.customerBasket && basketController.customerBasket.items && basketController.customerBasket.items.length > 0) {
            for (var i = 0; i < basketController.customerBasket.items.length; i++) {
                var cartItem = basketController.customerBasket.items[i];
                if (id == undefined || id == cartItem.product.id) {
                    total += cartItem.quantity;
                }
            }
        }

        return total;
    };

    basketController.getTotalAmount = function(cartItem) {
        var total = 0;
        if (cartItem) {
            total = (cartItem.quantity * cartItem.product.rrp_amount);
        }

        return total.toFixed(2);
    };

    basketController.getFinalTotalAmount = function() {
        var total = 0;
        if (basketController.customerBasket && basketController.customerBasket.items && basketController.customerBasket.items.length > 0) {
            for (var i = 0; i < basketController.customerBasket.items.length; i++) {
                var cartItem = basketController.customerBasket.items[i];
                total += (cartItem.quantity * cartItem.product.rrp_amount);
            }
        }

        return total.toFixed(2);
    };

    basketController.clearBasket = function() {
        StorageService.set("customer_basket", null);
        basketController.customerBasket = {
            shipping : null,
            taxRate : null,
            tax : null,
            items : []
        };

        $rootScope.$broadcast('customerBasketCleared', {});
    }

    basketController.saveBasket = function() {
        if (basketController.customerBasket) {
            StorageService.set("customer_basket", basketController.customerBasket);
            $rootScope.$broadcast('customerBasketSaved', {});
        }
    }

    basketController.checkout = function(serviceName, clearCart) {
        if (serviceName == undefined || serviceName == null) {
            serviceName = "PayPal";
        }

        switch (serviceName) {
            case "PayPal":
                basketController.checkoutPayPal(clearCart);
            break;
            default:
                throw "Unknown checkout service '" + serviceName + "'.";
        }
    };

    basketController.checkoutPayPal = function(clearCart) {
        if (basketController.customerBasket && basketController.customerBasket.items && basketController.customerBasket.items.length > 0) {

            // global data
            var data = {
                cmd: "_cart",
                business: '', //parms.merchantID,
                upload: "1",
                rm: "2",
                charset: "utf-8"
            };

            AppSettingService.getAppSetting(MERCHANT_ID_KEY).get().$promise
            .then(function(result) {
                data.business = result.value;

                for (var i = 0; i < basketController.customerBasket.items.length; i++) {
                    var cartItem = basketController.customerBasket.items[i];

                    var ctr = i + 1;
                    data["item_number_" + ctr] = cartItem.product.sku_code;
                    data["item_name_" + ctr] = cartItem.product.title;
                    data["quantity_" + ctr] = cartItem.quantity;
                    data["amount_" + ctr] = cartItem.product.rrp_amount.toFixed(2);
                }

                // build form
                var form = $('<form/></form>');
                form.attr("action", "https://www.paypal.com/cgi-bin/webscr");
                form.attr("method", "POST");
                form.attr("style", "display:none;");
                addFormFields(form, data);
                $("body").append(form);

                // submit form
                form.submit();
                form.remove();

                if (clearCart) {
                    try {
                        basketController.clearBasket();
                    } catch (exception) {

                    }
                }
            }).catch(function(reason) {
                console.log(reason);
            });
        }
    };

    basketController.viewBasket = function() {
        $location.path("/basket");
        $route.reload();
    };

    function addFormFields(form, data) {
        if (data != null) {
            $.each(data, function (name, value) {
                if (value != null) {
                    var input = $("<input></input>").attr("type", "hidden").attr("name", name).val(value);
                    form.append(input);
                }
            });
        }
    }

    return basketController;
}]);

My dilemma is as follows:

On my product page, I have product.html page (which is an angular view) and the "add to cart" button adds item to the cart but it doesn't update my cart summary button.

How do I make it that when I click the "add to cart" button that it update my cart and the number of items added to the cart?

The example image:

enter image description here

As you can see the orange button at the top right says that I have no items but there is 3 items in my cart already.

I tried various scoping allowed in directives but I seem to be failing to make it work.

PS: I am a newbie in AngularJS so please make your answer as simple to understand. :-)

The view product.html is linked to BasketController and this is the button that add item to cart.

<a class="btn btn-success btn-lg pull-right" role="button" ng-click="basketController.addCartItem(1, productController.selectedProduct)"><i class="fa fa-plus"></i> Add To Cart</a></div>
6
  • can you show the code where do you invoke addCartItem()? Commented Apr 15, 2016 at 9:48
  • @iulian, please see the updated code above. Commented Apr 15, 2016 at 13:41
  • you invoke basketController.addCartItem in your ProductController (or what is the controller of your product.html), but your basketController is defined only within your basketSummary directive. Commented Apr 15, 2016 at 13:46
  • There is a <div> element above which injects that basketController via ng-controller directive. Commented Apr 15, 2016 at 13:53
  • Have you checked in the console whether your addCartItem gets called when you click on that anchor? What are the arguments that this method gets called with? Commented Apr 15, 2016 at 13:56

1 Answer 1

1

You have an isolated scope issue. The controller of your directive is not the same as the controller you want to use in your product page. See: scopes

I would suggest you to create a factory, which is always a singleton where you store your basket products and inject them in both, the directive and the products page

Sign up to request clarification or add additional context in comments.

1 Comment

I did just that and I have the cart service injected on the BasketController only. Everything works as expected.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.