I am creating a client side shopping cart. Added products are saved in local storage, but how can increase product quantity if it is already added to local storage? I have function that adds product to local store and in this function I increase quantity, but products become duplicated.
Product.prototype.addObjToLocalStore = function() {
var obj = {
'name': this.name,
'qty': this.qty,
'price': this.price,
'total': this.getPrice()
}
var oldItems = JSON.parse(localStorage.getItem('itemsArray')) || [];
for (k in oldItems) {
if(oldItems[k].name == obj.name) {
oldItems[k].qty += parseInt(obj.qty);
localStorage.setItem('itemsArray', JSON.stringify(oldItems[k].qty));
}
}
oldItems.push(obj);
localStorage.setItem('itemsArray', JSON.stringify(oldItems));
}
Well, regardless of whether or not you've found the item, you oldItems.push(obj) to it, duplicating the item.
So what I would do in this case is not use an array, but an object. The key of the object being the item's identifier (in your case, the name), and the value being the item's properties (quantity, price, etc). Like so:
Product.prototype.addObjToLocalStore = function() {
// oldItems is an object, not an array
var oldItems = JSON.parse(localStorage.getItem('itemsObject')) || {};
// If it exists, grab its quantity. If not, 0.
var oldQuantity = (oldItems[this.name] && oldItems[this.name].qty) || 0;
var obj = {
'name': this.name,
'qty': oldQuantity + this.qty,
'price': this.price,
'total': this.getPrice()
}
// Replace the old entry with the new.
// If doesn't exist, will be created.
oldItems[this.name] = obj;
// We're done here. Store the new object.
logalStorage.setItem('itemsObject', JSON.stringify(oldItems));
};
If you want to not duplicate your object delete two last lines:
oldItems.push(obj);
localStorage.setItem('itemsArray', JSON.stringify(oldItems));
Related
I am creating a javascript cart.
Here's how I add a product to the cart:
function addToCart(id, qty){
var basket = []
basket.push({
product_id: id,
quantity: qty
});
localStorage.setItem('basket', JSON.stringify(basket));
}
Now if id is already there, I am trying only to update current basket from localStorage
When I add the same product id, it's duplicating it.
[{"product_id":"10", "quantity":"1"}, {"product_id":"10", "quantity":"1"}]
I want to increase only quantity like:
[{"product_id":"10", "quantity":"2"}]
Tried few methods with each and for with no luck :(
Any help please?
You're replacing your stored array every time, which won't have the problem you've described unless you don't really have the var basket = [] in your function. But the problem you've described would be caused by not checking for an existing entry with the product ID.
Instead:
Keep your array in memory, not just local storage
Load it from local storage on page load
Update it in local storage when you change your memory copy
Remove it from local storage when the user completes their purchase or clears their basket
For #1 and #2: In a place that's global to your code (but ideally not really global):
var basket = JSON.parse(localStorage.getItem("basket")) || [];
For #3:
function rememberBasket() {
localStorage.setItem('basket', JSON.stringify(basket));
}
function addToCart(id, qty){
// See if product exists
var entry = basket.find(function(e) { return e.product_id == id; });
if (entry) {
entry.quantity += qty; // Or just `= qty` to replace rather than adding
} else {
basket.push({
product_id: id,
quantity: qty
});
}
rememberBasket();
}
For #4, of course:
basket = [];
rememberBasket();
Your original code was all ES5 and earlier, so I stuck to that above, but ES2015+ features would make it more concise.
Solution :
function addToCart(id, qty) {
var newItem = true;
var basket = json.parse(localStorage.getItem('basket'));
basket.forEach(function (item){
if(item.product_id == id) {
item.quantity += qty;
newItem = false;
}
})
if(newItem) {
basket.push({
product_id: id,
quantity: qty
});
localStorage.setItem('basket', JSON.stringify(basket));
}
}
First, you need to try to read the basket out of localStorage instead of starting with an empty array each time. Second, I'd recommend you use an object instead of an array. Your products already have ids, so instead of searching the array each time, just let the language do the key lookup for you. Last, you're missing any treatment of how to update existing items in the cart. Here's how I'd approach that, supporting both adding new items to the cart, and increasing the quantity of existing items.
function addToCart(id, qty){
var basket = JSON.parse(localStorage.getItem('basket')) || {};
if (basket[id]) {
basket[id] += qty;
} else {
basket[id] = qty;
}
localStorage.setItem('basket', JSON.stringify(basket));
console.log(basket);
}
addToCart(1,1);
addToCart(2,1);
addToCart(1,1);
addToCart(3,2);
addToCart(3,1);
// results in:
VM222:9 {1: 1}
VM222:9 {1: 1, 2: 1}
VM222:9 {1: 2, 2: 1}
VM222:9 {1: 2, 2: 1, 3: 2}
VM222:9 {1: 2, 2: 1, 3: 3}
Try this
function addToCart(id, qty){
var basket = JSON.parse(localStorage.getItem('basket'));
var isExists = false;
if(basket === null || basket === undefined){
basket = [];
}
basket.reduce(function(o,i){
if(i.product_id === id){
i.quantity += qty;isExists = true;
}
o.push(i);
return o;
},[]);
if(!isExists){
basket.push({
product_id: id,
quantity: qty
});}
localStorage.setItem('basket', JSON.stringify(basket));
}
I have a program that pushes values into one data structure like this:
if(symbolType == "C" || symbolType == "P") // The calls and puts
stocks.push({
symbol: symbol,
undsymbol: undSymbol,
open: 0,
type: symbolType,
expiry: expiry,
days: days,
strike: strike
});
}
else // The stock
{
stocks.push({
symbol: symbol,
open: 0,
type: symbolType
});
}
So this is the key: NOT A STRING!
{
symbol: symbol,
open: 0,
type: symbolType
}
And the values of which are many look like this:
{
symbol: symbol,
undsymbol: undSymbol,
open: 0,
type: symbolType,
expiry: expiry,
days: days,
strike: strike
}
The problem is that stocks and calls and puts are being put into one collection. Instead, I want to add the the stocks and their corresponding calls and puts into a dictionary/map, where the stocks are the keys, and the calls and puts get pushed into an array indexed by it's stock.
At the end, I want to be able to iterate and get the keys and values.
How do I declare this object
Index into it to see if the key[stock] already exists, if it doesn't add it with an empty array.
If I get a "C" or "P", I want to get the corresponding array that holds the Calls/Puts for this key [stock] and push the call/put into the array.
Initially I thought the declaration was something like this:
var stockCallsPutDict = {[]}
stockCallsPutDict[stock] = [];
stockCallsPut[stock].push(call);
// Pretty print the dict of keys and its options =
stockCallsPutDict.forEach(function kvp) {
...
}
If ES6 is an option, you can either build an object yourself or use a Map.
Here's some quick code I came up with:
const stocks = {};
const addCallAndPut = callAndPut => {
const symbol = callAndPut.symbol;
if (!stocks[symbol]) {
stocks[symbol] = [];
}
stocks[symbol].push(callAndPut);
}
const showStuff = () => {
for (const symbol in stocks) {
// output stuff using stocks[symbol]
}
}
OR WITH A MAP
const stocks = new Map();
// basic implementation
const addCallAndPut = callAndPut => {
const stockCallsAndPuts = stocks.get(callAndPut.symbol) || [];
stockCallsAndPuts.push(callAndPut);
stock.set(callAndPut.symbol, stockCallsAndPuts);
}
There are a few ways to go about this, and the best depends on how the data needs to be processed later, but from your description I'd go with something along the lines of
var stocks = {};
var stockCallsPut = {};
// loop over stocks and actions
if (!(symbol in stocks)) {
stocks[symbol] = [];
}
if (!(symbol in stockCallsPut)) {
stockCallsPut[symbol] = {};
}
if (!(symbolType in stockCallsPut[symbol])) {
stockCallsPut[symbol][symbolType] = [];
}
// accumulated stock json items here
stocks[symbol].push(new_stock_item);
// accumulated push/call json items of stock here
stockCallsPut[symbol][symbolType].push(new_action);
I'm still not sure I actually understood what your data looks like, but sounds kind of like this to me:
// Not sure if data is an object or array
var data = {
'one': {
'name': 'one-somename',
'number': 'one-somenumber',
'symbol': 'C'
},
'two': {
'name': 'two-somename',
'number': 'two-somenumber',
'symbol': 'P'
},
'three': {
'name': 'three-somename',
'number': 'three-somenumber',
'symbol': 'C'
}
};
var stocks = {};
for (var name in data) {
// It sounded like you wanted a call/put array for each object but I'm not sure if that's true since it wouldn't be possible... if so can just divide this part up into it's appropriate place in the if statement below
// Checking that the property is set on the object, if it is, it uses itself, otherwise it adds it with the call/put arrays created
stocks[name] = stocks[name] ? stocks[name] : {'calls': [], 'puts': []};
var type;
if (data[name]['symbol'] === 'C') {
type = 'calls';
} else if (data[name]['symbol'] === 'P') {
type = 'puts';
}
stocks[name][type].push(data[name]);
}
I have an array of objects with about 1,500 elements
var a = [
{
'name': 'jug',
'price': 0,
},
{
'name': 'watermelon',
'price': 47,
},
{
'name': 'pizza',
'price': 0,
},
{
'name': 'handkerchief',
'price': 52,
},
..........................
]
I keep updating the array with prices as i get data.
I need to re-order the elements with with prices and keep the ones that were on top in the same order.
If that is not so clear lets say you had a web page with products in a certain order, and prices are loading for the products in batches.
I want to put the prices on top and keep it in that order so the products don't jump around. however when i get prices i would like to push it to the bottom after the last price on the list.
try
a.sort(function(a,b){
var priceA = a.price? a.price : Number.MAX_SAFE_INTEGER;
var priceB = b.price? b.price : Number.MAX_SAFE_INTEGER;
return a.price-b.price;
});
This will ensure that if price is not available, they will stay at the bottom.
In order for this to work, you need to have the indexOfObj, which is the index of the needed object in your array:
var updatedElement = a.splice(indexOfObj, 1); // Remove the element with the updated price
a.push(updatedElement); // Add the new element to the end of the 'a' array.
Ok I'm making a few assumptions here because the question is not very clear to be honest. But I believe you want to do something like this:
(assuming newprices is a batch of update data)
// if product already in list update price, otherwise insert at bottom
var i, index, newprice;
for(i = 0; i<newprices.length; i++) {
newprice = newprices[i];
index = a.findIndex(function(p) { return p.name === newprice.name; });
if(index > -1) { a[index].price = newprice.price; }
else { a.push[newprice]; }
}
Or maybe you want to do something like this:
// put items that get updated prices or are new altogether at the end of the list
var i, index, newprice;
for(i = 0; i<newprices.length; i++) {
newprice = newprices[i];
index = a.findIndex(function(p) { return p.name === newprice.name; });
if(index > -1) { a.splice(index, 1); }
a.push[newprice];
}
But yeah it would definitely help if you state more clearly what you're trying to do...
Hello i am trying to create a simple client side cart, in my controller when the page loads i define the array objects that will hold my items, if they are undefined or have a length of 0 i set them to '[]' by default:
$scope.cart = JSON.parse($window.localStorage.getItem('cart')) || [];
$scope.cart.items = $scope.cart.items || [];
This is the function that adds the item to the cart:
$scope.addItem = function(item) {
if (item.quantity > 0)
{
var cartItem = {
id: item.id,
description: item.class + ' item' + (item.quantity > 1 ? 's' : '') + ' to ' + $scope.details.name,
quantity: item.quantity
}
// Adding item to cart array
$scope.cart.items.push(cartItem)
// Saving cart to storage
$window.localStorage.setItem('cart', JSON.stringify($scope.cart));
// Checking to see if data has indeed been stored in localstorage
console.log(JSON.parse($window.localStorage.getItem('cart')));
}
}
Now my cart in storage always turns up as empty, there were times i played around with the code and got it to work(dunno what i did) but when i reloaded the page everything got cleared.
You are initializing cart as array but then assigning properties to it.
It should be an object:
$scope.cart = JSON.parse($window.localStorage.getItem('cart')) || {};
Also before you can push to an array within cart that array needs to be defined.
Simplest might be to have all the properties available in one object first:
var newCart = {
tickets:[],
items:[]
}
$scope.cart = JSON.parse($window.localStorage.getItem('cart')) || newCart ;
You should check if there is already a value stored as
if(!$window.localStorage.getItem('cart'))
{
// Saving cart to storage
$window.localStorage.setItem('cart', JSON.stringify($scope.cart));
}
I'm working on choices gathering app and I got stuck at working with objects:
User have list of cards, each card have list of choices, each choice have id and price. I want to gather user selection at each card and than count final price. I don't know exact names of cards, they will be generated. I know only the class of selected card or card list count.
data collection:
var datacollection = {
shape: {
itemId: 1,
price: 10
},
countmoney: function () {
var cash = 0;
$.each(this, function (id, item) {
if (typeof (item) != 'function') {
cash += item.price;
}
});
return cash + ' $';
}
};
data gathered from .click(function() {
var cardClass = 'color';
var choiceId = 2;
var choicePrice = 50;
I can insert new data, but ONLY if I know name of the card
datacollection.color = {
itemId: choiceId,
price: choicePrice
};
But what if I don't know the possible name of card? Using bracket notation should be the way to go.. but it doesn't work.
cardClassTwo = 'material';
datacollection[cardClassTwo]['itemId'] = choiceId;
datacollection[cardClassTwo]['price'] = choicePrice;
// Uncaught TypeError: Cannot set property 'itemId' of undefined
console.log(datacollection.countmoney());
Code to play with: http://jsfiddle.net/F5pt6/
Initialize your datacollection['material'] as an object, like you did before.
Also, refer to values correctly (if they are in your previous object):
datacollection[cardClassTwo] = {
itemId: datacollection.color.itemId,
price: datacollection.color.price
};