0

So i have a productList and cart where i store products, when i add product to cart(localStorage), products count must async refreshed, but it refreshed only with refreshing a page (this is about goodsInCart). Maybe it needed to adding EventListener? Please tell me where i was wrong.

products.html

<div ng-controller="ProductController">
    <div class="container">
        <h1 class="page-header">Product List</h1>
         <div class="small-cart">
            <a href="#!/cart">
              <span class="amount">{{goodsInCart}}</span>
              <img class="cart" src="./images/cart_2.png">
            </a>
          </div>
         <div class="row">
            <div class="item col-sm-6 col-md-4 col-lg-3" ng-repeat="product in products">
                <h3>{{product.title}}</h3>
                <img class="product-photo" src="{{product.photoURL}}" alt="">
                <p>{{product.price}} UAH</p>
                <button class="btn btn-cart" ng-click="addToCart(product)">Add to cart</button>
            </div> 
        </div>
     </div>
</div>

ProductService.js

testApp.factory('CartProduct', function(localStorageService) {
  var cartProducts = [];
  var goodsInCart = 0;

  function init() {
    checkCartChanged();
    if (localStorageService.get('cart-products')!=null) {
      cartProducts = localStorageService.get('cart-products');
      calcGoodsInCart();
    }
  }

  init();

  function getAll() {
    return cartProducts;
  }

  function addToCart(product) {
      cartProducts.push({product : product,amount : 1});
      refresh();
    }

  function store(key,value) {
     localStorageService.set(key, value);
  }

  function calcGoodsInCart() {
     var temp = 0;
     temp = cartProducts.length;
     goodsInCart = temp;
     return goodsInCart;
  }

  function getStorageItem(key) {
    for (var i = 0; i < localStorageService.length(); i++) {
        return localStorageService.get(key);
    }
    return null;
  }


  function checkCartChanged() {
    const storedGoods = getStorageItem('goods');
    cartProducts = storedGoods ? storedGoods : [];
    calcGoodsInCart();
  }  

  function refresh () {
    store("goods",cartProducts);
    calcGoodsInCart();
  }

  function deleteAllProducts() {
    this.localStorageService.clear('goods');
  }

  function findCartItem(product){
    for(let i =0; i < cartProducts.length;i++){
      if (product.id == cartProducts[i].product.id) {
        return i;
      }
    return -1;
    }
  }

  function deleteProduct(product){
    let index = findCartItem(product);
    if (index < 0) {
      return;
    }
    cartProducts.splice(index, 1);
    refresh();
  }

  function deleteAllProducts() {
    localStorageService.clear('goods');
  }

  return {
    addToCart: addToCart,
    getAll: getAll,
    calcGoodsInCart:calcGoodsInCart,
    getStorageItem:getStorageItem,
    deleteProduct:deleteProduct,

    goodsInCart:goodsInCart
  };
});

ProductController.js

testApp.controller('ProductController',function ProductController($scope,$http,CartProduct) {
    $scope.products = [
       { id:1, title: 'Margarita', photoURL:'...',price:260},
       { id:2, title: 'Margarita', photoURL:'...', price:240},
       { id:3, title: 'Margarita', photoURL:'...', price:200},
       { id:4, title: 'Margarita', photoURL:'...', price:190}
    ]; 

    $scope.addToCart = function (product) {
        CartProduct.addToCart(product);
    }

    $scope.goodsInCart = CartProduct.goodsInCart;

});
  • What's `localStorageService`? a custom service or a third party one? – lealceldeiro Aug 14 '18 at 20:15
  • Please consider to provide a [Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve) if possible. This way, it's more likely volunteers on SO can help you. – lealceldeiro Aug 14 '18 at 20:17
  • use $scope instead of var. In addToCart you just assign the total length of cartProducts to $scope.goodsInCart. Thats it ! – Mirza715 Aug 14 '18 at 21:06
  • **localStorageService** it`s AngularJS library to work with localStorage - https://www.npmjs.com/package/angular-local-storage – Taras Danylchenko Aug 14 '18 at 22:32

1 Answers1

1

There are two problems with your approach, the first one is that you're saving only the first value of goodsInCart in your controller in the line $scope.goodsInCart = CartProduct.goodsInCart;.

The second one is that you're exposing only values instead of references.

The solution would be to wrap goodsInCart inside an object and provide its reference instead.

testApp.factory('CartProduct', function(localStorageService) {
  var cartProducts = [];
  var sharedObj = {
    goodsInCart: 0
  }

  ...

  function calcGoodsInCart() {
    var temp = 0;
    temp = cartProducts.length;
    sharedObj.goodsInCart = temp;
    return temp;
  }

  ...

  return {
    addToCart: addToCart,
    getAll: getAll,
    calcGoodsInCart:calcGoodsInCart,
    getStorageItem:getStorageItem,
    deleteProduct:deleteProduct,

    sharedObj:sharedObj
  };

Note: Be careful when trying to share an object, if you change the reference of sharedObj inside your factory, any of the controllers that use it will lose the reference. That's why you should modify only the attributes of the shared obj.

Then you can use the provided object in your controller like this:

$scope.sharedObj = CartProduct.sharedObj;

Hope it helps!

Rodrigo Ferreira
  • 1,091
  • 8
  • 11
  • thanks, it works. You say that i exposing only values instead of references. Is it better way to wrap it in obj or there is better ways? – Taras Danylchenko Aug 17 '18 at 21:14
  • It depends on what would be your approach, the top 2 most voted answers to [this question](https://stackoverflow.com/q/21919962/8371135) will give you all the information you need, I particularly prefer the 2nd one (avoiding the explicit watchers). – Rodrigo Ferreira Aug 17 '18 at 21:30