I'm trying to implement a Product Cart behavior, and I have a navigation bar which contains the Cart UI element. The service UserCart.js handles product add/remove. This service is used in NavController, which should get updated each time the Product is added or removed. All the UI bindings in Cart element work perfectly, except the portion which I'm binding to the associative array which contains the cart product information. Its key is Product ID, and value is an object {Quantity:Z, CostPerUnit: Y}
UserCart.js
(function() {
// Get reference to the app
var app = angular.module("jargoViewer");
// Create the factory that share the User Cart with various controllers
app.factory('UserCart', function(){
var cart_items = [];
var cart = {
cart_val: 0,
cart_size : 0,
cart_products : [],
cart_prod_ids : []
};
var addProductInCart = function(prodID, prodCostPerUnit, prodQuantity) {
console.log('BEFORE Came inside addProductInCart total_cart_val:'+cart.cart_val);
console.log('Came inside addProductInCart prod:'+prodID + ', costPerUnit:'+prodCostPerUnit+',quantity:' + prodQuantity);
if((prodID in cart_items)) {
// true if "prodID" exist in cart_items
// Add the new prodID key element now
prodObj = cart_items[prodID];
prodObj.Quantity = prodObj.Quantity + prodQuantity;
// TODO DELETE
cartProdObj = cart.cart_products[prodID];
cartProdObj.Quantity = cartProdObj.Quantity + prodQuantity;
} else {
// A product with same key doesnt exists
cart_items[prodID] = {
'Quantity' : prodQuantity,
'CostPerUnit' : prodCostPerUnit
};
// TODO DELETE
cart.cart_products[prodID] = {
'Quantity' : prodQuantity,
'CostPerUnit' : prodCostPerUnit
};
}
// Add the total newly added products cost to Total Cart Value
cart.cart_val += prodCostPerUnit * prodQuantity;
cart.cart_size += 1;
cart.cart_prod_ids.push(prodID);
console.log('AFTER Came inside addProductInCart total_cart_val:'+cart.cart_val);
};
var removeProductInCart = function(prodID, prodQuantity) {
if((prodID in cart_items)) {
// true if "prodID" exist in cart_items
// Add the new prodID key element now
prodObj = cart_items[prodID];
existingQuantity = prodObj.Quantity;
prodCostPerUnit = prodObj.CostPerUnit;
if(prodQuantity > existingQuantity) {
alert('No more of this item exists in the cart!');
} else {
prodObj.Quantity = prodObj.Quantity - prodQuantity;
// Add the total newly added products cost to Total Cart Value
cart.cart_val -= prodCostPerUnit * prodQuantity;
cart.cart_size -= 1;
// TODO DELETE
cartProdObj = cart.cart_products[prodID];
cartProdObj.Quantity = cartProdObj.Quantity - prodQuantity;
if(prodObj.Quantity < 1) {
// No more of this product left in cart, remove from cart list
cart_items.splice(prodID, 1);
// TODO DELETE
cart.cart_products.splice(prodID, 1);
cart.cart_prod_ids.splice(prodID, 1);
}
}
} else {
// Error
alert('No more of this item exists in the cart!');
}
};
// Return the Interface of UserCart
return {
products_in_cart: cart_items,
cart : cart,
addProdInCart : addProductInCart,
delProdInCart : removeProductInCart
};
});
}());
The code for nav.html, and its controller NavController.js is as follows:
(function() {
var app = angular.module("jargoViewer");
var NavController = function($scope, UserCart) {
$scope.userCart = UserCart.cart;
$scope.cart_products = UserCart.products_in_cart;
};
app.controller("NavController", NavController);
}());
nav.html
<!-- Navigation -->
<nav id="mainNav" class="navbar navbar-default navbar-fixed-top navbar-custom">
<div class="container" ng-controller = "NavController">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header page-scroll">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span> Menu <i class="fa fa-bars"></i>
</button>
<a class="navbar-brand" href="#page-top">Jargo Foods</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right">
<li class="hidden">
<a href="#/main#page-top"></a>
</li>
<li class="page-scroll">
<a href="#/main#portfolio">Products</a>
</li>
<li class="page-scroll">
<a href="#/main#about">About</a>
</li>
<li class="page-scroll">
<a href="#/main#contact">Contact</a>
</li>
<!--
<li>
<p color:#fff>{{userCart.cart_val}} <i class="glyphicon glyphicon-shopping-cart" color:#fff></i></p>
</li>
-->
<li>
<div class="col-md-3">
<div id="cart" class="btn-group btn-block">
<button type="button" data-toggle="dropdown" class="btn btn-block btn-lg dropdown-toggle">
<i class="fa fa-shopping-cart"></i>
<span >Cart:</span>
<span id="cart-total" ng-show ="userCart.cart_size">{{userCart.cart_size}} item(s) - ₹ {{userCart.cart_val}}</span>
<i class="fa fa-caret-down"></i>
</button>
<ul class="dropdown-menu pull-right">
<div >{{userCart.cart_products}}</div>
<div class="row" ng-repeat="(id, obj) in userCart.cart_products">{{id}} {{obj}}</div>
<div class="row" ng-repeat="obj in userCart.cart_prod_ids">{{obj}}</div>
<li>
<table class="table table-striped hcart">
<tbody>
<tr ng-repeat="(id, itemObj) in cart_products">
<td class="text-center">
<a href="product.html">
<img src="img/others/cart.png" alt="image" title="image" class="img-thumbnail img-responsive">
</a>
</td>
<td class="text-left">
<a href="product-full.html">
Seeds
</a>
</td>
<td class="text-right">x {{itemObj.Quantity}}</td>
<td class="text-right">₹ {{itemObj.Quantity * itemObj.prodCostPerUnit}}</td>
<td class="text-center">
<a href="#">
<i class="fa fa-times"></i>
</a>
</td>
</tr >
</tbody></table>
</li>
<li>
<table class="table table-bordered total">
<tbody>
<tr>
<td class="text-right"><strong>Sub-Total</strong></td>
<td class="text-left">$1,101.00</td>
</tr>
<tr>
<td class="text-right"><strong>Eco Tax (-2.00)</strong></td>
<td class="text-left">$4.00</td>
</tr>
<tr>
<td class="text-right"><strong>VAT (17.5%)</strong></td>
<td class="text-left">$192.68</td>
</tr>
<tr>
<td class="text-right"><strong>Total</strong></td>
<td class="text-left">$1,297.68</td>
</tr>
</tbody>
</table>
<p class="text-right btn-block1">
<a href="cart.html">
View Cart
</a>
<a href="#">
Checkout
</a>
</p>
</li>
</ul>
</div>
</div>
</li>
</ul>
</div>
<!-- /.navbar-collapse -->
</div>
<!-- /.container-fluid -->
</nav>
Every binding works perfectly fine, except for the following:
<div >{{userCart.cart_products}}</div>
<div class="row" ng-repeat="(id, obj) in userCart.cart_products">{{id}} {{obj}}</div>
Please help figure what's wrong. Is there something special that needs to be done for associative array?
userCart.cart_products
in your template does not refer to anything in your $scope.
Try this instead
var NavController = function($scope, UserCart) {
$scope.userCart = UserCart.cart;
$scope.userCart.cart_products = UserCart.products_in_cart;
};
You could also you simply expose UserCart
in $scope :
var NavController = function($scope, UserCart) {
$scope.userCart = UserCart;
};
and in your template
<div >{{userCart.cart_products}}</div>
<div class="row" ng-repeat="(id, obj) in userCart.products_in_cart">{{id}} {{obj}}</div>
Okay, I figured out the problem. Being a newbie to JS, I had trouble understanding how the Associative Array (or more precisely MAP in JS) is defined. What I was doing was still declaring the array and trying to use it as a MAP
var cart = {
cart_val: 0,
cart_size : 0,
cart_products : [],
cart_prod_ids : []
};
The interesting part here is
cart_products : [],
This actually declares an ARRAY, and not a MAP. To fix the code, all I had to do was declare a MAP instead of array, all the other piece of code remaining the same!
cart_products : {},
This declares cart_products as a MAP, and then then the following would start to work
<div class="row" ng-repeat="(id, obj) in userCart.cart_products">{{id}} {{obj}}</div>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.