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));
}
Related
I want to change the values of the objects inside an array. I have created an object which I insert in every loop in an array.
If encountered with a missing value, I want to update the values of the existing object.
When the loop runs, it always enters the last object details from the api into the array.
Here; the screenshot: https://i.imgur.com/8uqOIaZ.png
var msg = data.message; // messages array from api
let body;
let posts = [];// empty array created
//object structure
let post ={
id:'',
desc: '',
creator: '',
time: '',
likes: 0,
attachment: '',
};
for(let i in msg){
if(msg[i].body.includes(':')){ //if message body include object notation ':'
body = JSON.parse(msg[i].body); // parse text message body into json
if(body.contentDescription){ //if content is true
post.id = body.postId; //id
post.creator = body.createdUserName; //post creator
post.time = body.publishedDate; //post publish date
post.desc = body.contentDescription; //post content
posts.push(post);
}
else if(posts.length > 1){
for(let j in posts){
if(posts[j].id === body.postId){
console.log(posts[j].id);
if(body.likeCount){ //if likeCount is true
posts[j].likes += 1; //increase like count
}else if(body.attachmentId){ //of Attachment is true
posts[j].attachment = body.attachmentId; // update attachement value
}
}
break;
}
}
}
};
Please help where am I doing it wrong?
Objects in JavaScript are sent via a link to the piece of memory. So when you change your post you are changing all the posts because all of them are looking to the same piece of memory.
You can change your code in a next way so it start working correct
...
if(body.contentDescription){ //if content is true
let postItem = Object.assign({}, post); // Coping an object so breaking the memory link
postItem.id = body.postId; //id
postItem.creator = body.createdUserName; //post creator
postItem.time = body.publishedDate; //post publish date
postItem.desc = body.contentDescription; //post content
posts.push(postItem);
}
...
However, there is more than one way to skin a cat so this is not the only solution.
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 am trying to save an array of "items" in the cart. but when it goes on else section an error occur "Uncaught TypeError: Cannot read property 'items' of null" please help what's wrong with the code
var existing_cart = localStorage.getItem("cart");
existing_cart = JSON.parse(existing_cart);
console.log(existing_cart);
if (existing_cart.items instanceof Array) {
existing_cart.items.push({
'article_number': article_no,
'quantity': quantity,
'item_name ': item_name
});
console.log(existing_cart);
localStorage.setItem("cart", JSON.stringify(existing_cart));
} else {
var products = [{
'article_number': article_no,
'quantity': quantity,
'item_name ': item_name
}];
var cart = {
'items': products
}
localStorage.setItem("cart", JSON.stringify(cart));
toastr.success('Have fun storming the castle!', 'Miracle Max Says');
}
The first time you run the code there won't be anything in the local storage, so existing_cart will be null. You need to check for this.
Change
if (existing_cart.items instanceof Array) {
to:
if (existing_cart) {
var existing_cart = localStorage.getItem("cart") || '{"items":[]}';
In the case that it is the first time the code runs, the localStorage may not have the element, in which case it will return null or undefined. In that case you can default it to a JSON that will allow the logic to flow without encountering null pointer exceptions.
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));
Little change of my code and it's partially works :)
var db = {
hotels: JSON.parse(localStorage.getItem('table') || "[]"),
get objects() {return this.hotels},
set objects(obj) {
obj = this.hotels;
localStorage.setItem('table', JSON.stringify(obj))
}
}
jQuery(function(){
var count = localStorage.getItem('count');
if(!count) {
count = 0;
}
function Add(item){
var client = {
ID : jQuery(item).find("#txtID").val(),
Name : jQuery(item).find("#txtName").val(),
Photo : jQuery(item).find("#txtPhone").val(),
Link : jQuery(item).find("#txtEmail").val()
};
db.objects = db.objects.push(client);
count = count+1;
localStorage.setItem('count',count);
jQuery('.panel2 a span').text('('+ localStorage.getItem('count') +')');
jQuery(item).find('.add_rem').hide();
jQuery(item).find('.remove').show();
jQuery("#tblList .empty").hide();
jQuery("#tblList").find('li:gt(0)').remove();
jQuery.each(db.objects,function(i,element) {
jQuery("#tblList").append("<li class='added"+db.objects[i].ID+"'>"+
"<img src='../../images/general/delete.gif' alt='Delete"+i+"' class='delete'/>" +
"<a href='"+db.objects[i].Link+"' title='"+db.objects[i].Name+"'>"+
" <img src='"+db.objects[i].Photo+"' alt='"+db.objects[i].Name+"'>" +
" <span>"+db.objects[i].Name+"</span>" +
" </a>" +
"</li>");
})
return true;
}
function Delete(item){
jQuery(item).prev('.add_rem').show();
jQuery(item).find('.remove').hide();
jQuery(item).find('.remove').removeAttr('alt');
}
function List(){
if(count > 0) {
jQuery("#tblList .empty").hide();
jQuery('.panel2 a span').text('('+ localStorage.getItem('count') +')');
}
for(var i= 0; i<= count; i++) {
var cli = JSON.parse(db.hotels);
if(cli[i] != null){
jQuery("#"+cli[i].ID).find('.add_rem').hide();
jQuery("#"+cli[i].ID).find('.remove').show();
jQuery("#"+cli[i].ID).find('.remove').attr('alt','Delete'+i);
jQuery("#tblList").append("<li class='added"+cli[i].ID+"'>"+
"<img src='../../images/general/delete.gif' alt='Delete"+i+"' class='delete'/>" +
"<a href='"+cli[i].Link+"' title='"+cli[i].Name+"'>"+
" <img src='"+cli[i].Photo+"' alt='"+cli[i].Name+"'>" +
" <span>"+cli[i].Name+"</span>" +
" </a>" +
"</li>");
}
}
}
jQuery("#frmCadastre").bind('submit',function(e){
e.preventDefault()
return Add(this);
});
List();
jQuery(".remove, .delete").bind("click", function(e){
e.preventDefault();
Delete(this);
List();
});
})
now my question is how to push element to array after page refresh this is located in function Add()
array looks like this
"["{"ID":"1","Name":"test","photo":"/link/to/photo.jpg"}"]"
and if i add another element before page refresh it works great
"["{"ID":"0","Name":"test0","photo":"/link/to/photo0.jpg"}","{"ID":"1","Name":"test1","photo":"/link/to/photo1.jpg"}"]"
but if i Reload page and try to add an element Firebug is throwing:
`TypeError: db.objects.push is not a function
db.objects = db.objects.push(client);`
We will start to clear out what happens with HTML5 Local Storage. Local storage is a place in your disk defined by every browser that supports it. These places may be different for every browser. They hold tuples with keys and values, both strings. If you want to save a whole object to the disk, you must serialize it. That means you have to transform it into an array of data, in our case chars -> string. In javascript the most common object serialize function is JSON.stringify. Its input is a valid JSON object, which in our case is an array and it will make it into a string using the literals you use to initialize an object like {x:5}. JSON.stringify([{x:5},{x:6},{x:7}]) will have the following output: "[{x:5},{x:6},{x:7}]". And to reconstruct your object from a string you use JSON.parse(x) where x is a valid json string. You want now to have an array of objects, the first thing you'll think of is to serialize your array you have as a var in your program and add a special key you remember to store it into your disk. Each browser has seperate localStorage for every site that is hosted by a server.
An example that stores a value bound to a key in localstorage is this:
localStorage.setItem('x','5');
localStorage['x'] = 5;
localStorage.x = 5;
all of them do the same thing, and their speed is in descending order. Now you have at Chrome->resources->localstorage:
+-------------------+
| Key | Value |
+---------+---------+
| x | "5" |
+---------+---------+
When you make your first visit to the page, you have nothing in localStorage, so you must have some initial values. Trying to get a value by:
return localStorage.getItem('x');
return localStorage['x'];
return localStorage.x;
will give you undefined. There is a nice operator made in javascript and is the ||.
null || 5 //returns 5
undefined || 3.14 //returns 3.14
'' || 6 //returns 6
[] || {} //returns []
If the left operand "exists", return it, else return the right one. This makes things faster with localStorage.getItem('x') || 5 so if a tuple with key x exists it will return the value of the item with the specified key, else it will return the 5, which is our initial value.
Let's get back to the localStorage again. Remember the tuples are saved into the disk, which is vastly slower to access than things in ram. If I want to read the value of an item in the localStorage let say in a loop, several times, should I read it directly from the disk, or should I read it once from the disk and save it into ram to access it faster? You surely know what makes more sense...So I must have a variable that is the clone of the one in the localStorage. Let's say I name it private_var. It must have an initial value which will be:
var private_array = JSON.parse(localStorage.getItem('array')) || [];
When you want to change your array in localstorage (e.g pushed an item) you use:
private_array.push(item)
localStorage.setItem('array', JSON.stringify(private_array))
Your localstorage will be like:
+---------+-----------------------------------------+
| Key | Value |
+---------+-----------------------------------------+
| array | [{"name":"george", "surname":"bush"}] |
+---------+-----------------------------------------+
To make things faster in terms of code production, not program speed you can define setters and getters.
var obj = {
temp: 5,
get x( ) { return this.temp },
set x(value) { this.temp = value }
}
we have an object named obj, a member temp and a setter and a getter function, just like in some java code. You can check obj.temp === 5. These special operators allow us to write
obj.x = obj.x + 6;
and it will be executed as something like this:
obj.set_x(obj.get_x() + 6);
So let's say you have an interface named db (database, similar to what a locastorage is) and a "private member" which is clearly not. You can see an implementation at http://ejohn.org/blog/javascript-getters-and-setters/ with __define(G/S)etter__ which has real private member, but this one is surely faster to write and more readable.
var db = {
cl_arr: JSON.parse(localStorage.getItem('array')) || [],
get clients( ) { return this.cl_arr },
set clients(v) {
localStorage.setItem('array', JSON.stringify(this.cl_arr));
if(v.constructor === Array) { this.cl_arr = v }
}
}
so when I execute:
db.clients.filter(function(client) { return client.money > 1000 });
this will be executed
db.get_clients().filter...;
And when I try to change the array, I will write this
db.clients = db.clients.push(client);
Even if the push method can change the array, only the get function will be triggered so only the "private" cl_arr variable will change, to trigger the setter which updates our localStorage too I have to write the db.clients = ...