updating a multidimensional array stored in session storage - javascript

I have taken over a project and am not totally familiar with JQuery and session storage. The issue is that after updating the info and clicking update it provides an error, "Uncaught SyntaxError: Unexpected token u in JSON at position 0
at JSON.parse (<anonymous>)
at fillArray (main.js? [sm]:313)
at UpdateProduct (main.js? [sm]:234)
at HTMLButtonElement.onclick ((index):405)".
Included link to github repo:https://github.com/bveasey/Jquery-project
function UpdateProduct() // called on click of an update btn
{
// capture id from hidden element set in editproduct function
var productId = $('#txtHiddenId').val();
console.log("***** line:233 *****\n product id =" + productId);
fillArray(productId);
console.log("***** line:235 *****\n Fill array called!");
BindTable();
console.log("***** line:237 *****\n Bind Table called!");
}
// other functions
function fillArray(prodid)
{
console.log("***** line:310 *****\n Begin Fill Array");
// find the item in the product array and update it
$.each(JSON.parse(sessionStorage.setItem('products',
JSON.stringify(productArray))), function (idx, v)
{
console.log("***** line:315 *****\n " + product.id);
// Check if current prodid is the id wanted
if (product.id === prodid)
{// ids match
console.log("***** line:319 *****\n product is's match");
// populate data
product.id = productId;
product.arrivalDate = $('#modalRequestedArrivalDate').val();
product.productCode = $('#modalProductCode').val();
product.description = $('#modalDescription').val();
product.quantity = $('#modalQuantity').val();
product.quantityType = $('#modalQuantityType').val();
product.plant = $('#modalPlant').val();
product.shippingMethod = $('#modalShippingMethod').val();
product.specialInstructions = $('#modalSpecialInstructions').val();
console.log("***** line:310 *****\n END Fill Array");
}
});
}
// bind table just updates the table.

Storage#setItem() returns void, you can't parse void using JSON.parse(), void is not valid JSON syntax.
The Error tells you exactly where the problematic code is,
$.each(JSON.parse(sessionStorage.setItem('products', JSON.stringify(productArray))), function (idx, v)...
The sessionStorage.setItem() here doesn't return anything that the JSON.parse() can parse.

Related

Remove entire array from local storage

How to remove the localStorage entirely without localStorage.clear(); method?
I have a cart where you can store the products you're about to buy and the storing happens with a local storage. Currently the "Clear Cart" button works with localStorage.clear(); method, but I also have a table where you can remove single products. However, if you remove the entire table with the "remove" button on the same row and it happens to be the last product, local storage will still have an empty array and is considered as NOT null.
This is my method to remove the item:
function removeItem(itemId) {
//removes the parent row of table
$('#product-table').on('click', '.remove-item', function(e) {
$(this).closest('tr').remove();
});
var index = -1;
var obj = JSON.parse(localStorage.getItem("items")) || {}; //fetch cart from storage
var items = obj || []; //get the products
$.each(items, function(key, value) {
if (key === itemId) {
items.splice(key, 1); //remove item from array
}
});
localStorage.setItem("items", JSON.stringify(obj)); //set item back into storage
sum = 0;
$.each(items, function(key, value) {
sum += value.itemPrice;
});
$("#summary").html(sum.toFixed(2) + "€");
updateCartCount();
}
It removes items correctly, but whenever I remove the last product, the table element and add a paragraph saying "Your cart is empty. Return to shop".
Following function is below:
function hideElements() {
if ($(".cart-wrapper").length) {
if (localStorage.getItem("items") === null) {
$("#products").css("display", "none");
$("#empty").css("display", "block");
$(".btn-clear").css("display", "none");
} else {
$("#products").css("display", "block");
$("#empty").css("display", "none");
$(".btn-clear").css("display", "block");
}
}
}
The hideElements function won't recognize the local storage as empty, since it shows that there is an empty array object.
How can I achieve this by removing the entire local storage, if the removed product was the last product on the cart? I tried out with localStorage.getItems("items").length != 0 and such with no avail.
The following image displays my "empty" local storage:
What localstorage.get() returns is a string rather than JSON so what you need to do is parse string i.e. localStorage.getItem('items') returns "[]" which has length equal to 2. What you need to do is JSON.parse(localstorage.getItem('item')).length
You're probably looking for localStorage.removeItem().
Better yet, you should refactor things so there are functions solely responsible for managing the items array in your local storage:
function loadItems() {
// Returns the value of items, or an empty array.
return JSON.parse(localStorage.getItem("items") || "[]");
}
function saveItems(itemsArr) {
localStorage.setItem("items", JSON.stringify(itemsArr));
}
// Remove item with given ID (assuming each element in the array is e.g. `{id: 123}`)
const itemId = 123;
saveItems(loadItems().filter(item => item.id !== itemId));
// Update cart HTML elements:
if ($(".cart-wrapper").length) {
const haveItems = loadItems().length > 0;
$("#products").toggle(!haveItems);
$("#empty").toggle(haveItems);
$(".btn-clear").toggle(!haveItems);
}

name.forEach is not a function after button is clicked

I am trying to edit/update current data using the contenteditable attribute which I have successfully enabled onclick. My 'enter' key allows the data to be submitted. However, the console.log reads that a PUT request has been made for a particular list item but without the 'title' or 'isbn' being updated along with it.
Another prominent issue is that my console.log shows books.forEach is not a function, and I have no idea why this is the case since the code inside that function is processed.
HTML ('li' items are solely JS-Generated with a POST request)
<div id="divShowBooks">
<li id="[object HTMLParagraphElement]">
<p id="24" name="anID" placeholder="24">1</p>
<p id="TEST" name="aTitle" placeholder="TEST">TEST</p>
<p id="12345" name="anISBN" placeholder="12345" contenteditable="true">12345</p>
<button>Delete</button>
</li>
</div>
JavaScript
var book_list = document.querySelector('#divShowBooks');
book_list.innerHTML = "";
var books = JSON.parse(this.response);
books.forEach(function (book) {
// Text information to be displayed per item
var id = document.createElement('p');
id.type = 'text';
id.innerHTML = book.id;
var title = document.createElement('p');
title.type = 'text';
title.innerHTML = book.title;
var isbn = document.createElement('p');
isbn.type = 'text';
isbn.innerHTML = book.isbn;
// Defining the element that will be created as a list item
var book_item = document.createElement('li');
// Displays id, title and ISBN of the books from the database
book_item.appendChild(id);
book_item.appendChild(title);
book_item.appendChild(isbn);
// Creates an ID attribute per list item
book_item.setAttribute("id", id)
// Assigns attributes to p items within book items
id.setAttribute("id", book.id)
title.setAttribute("id", book.title)
isbn.setAttribute("id", book.isbn)
// Adding a generic name to these elements
id.setAttribute("name", "anID")
title.setAttribute("name", "aTitle")
isbn.setAttribute("name", "anISBN")
title.addEventListener('click', function (e) {
e.preventDefault();
title.contentEditable = "true";
title.setAttribute("contenteditable", true);
title.addEventListener('keypress', function (e) {
if (e.keyCode === 13) {
e.preventDefault();
xhttp.open("PUT", books_url + '/' + book.id, true);
var editTitle = new FormData() /
editTitle.append("title", document.getElementsByName("aTitle")[0].value)
xhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded')
xhttp.send(); //
}
});
});
UPDATE
I have added the following to my code. This seems to display my database items as an array in the log. But, I am now having a similar issue with Uncaught TypeError: JSON.parse(...).map is not a function:
var params = [
id = 'id',
title = 'title',
isbn = 'isbn',
createdAt = 'createdAt',
updatedAt = 'updatedAt'
];
var books = JSON.parse(this.response).map(function(obj) {
return params.map(function(key) {
return obj[key];
});
});
console.log(books);
UPDATE 2
Here is an image of what I receive in the console.log. The first part displays the original JSON content and the second is my attempt to convert each object into an array.
See Image
You have to make sure that your books variable actually contains an Array after parsing.
Alternatively, but this wouldn't make sense, just to address the "books.forEach is not a function" issue, You can use Object.assign([], this.response);. To make sure that books will contain an array, you wrap it in a try catch and make something like this:
var books = [];
try {
books = Object.assign([], this.response);
} catch (error) {
books = [];
}
books.forEach will then be expected to always work but you have to be careful because something like this could happen:
var myStringObject = "{'myProperty':'value'}";
var myArray = Object.assign([], myStringObject );
//myArray value is ["{", "'", "myProperty", "'", ":", "'", "value", "'", "}"]
Which will leave you having to check the book in your forEach callback if it is correct:
//at the topmost of your forEach callback
if(!book.id) throw BreakException; //A simple break will not work on forEach
This will leave you again with another exception to handle. Or leave you having to use the traditional for loop since you cannot short circuit Array.forEach with a break.
TLDR: make sure books always contains an Array.
You are getting books from JSON.parse(), which means books is an object and not an array.
forEach is an array method.
Try console logging books and look for an array inside of it.

JQuery onclick parameter passing with append

Im currently trying to append a variable amount of text to a list. Each item would need to be clickable with their own value being passed to a function. I cannot seem to get this to work and keep getting a 'Object' is not defined at HTMLAnchorElement.onclick error, where object is the name of the object in the list. Here is the code that I am using for this:
if (user) {
id = user.uid;
ref = firestore.collection("Users").doc(id);
console.log(user);
console.log(ref.get());
ref.get().then(function(doc){
nameString = doc.data().name;
console.log(nameString);
const outputHeader = document.querySelector("#headMain");
const outputInfo = document.querySelector("#genInfo");
outputHeader.innerText = "Welcome " + nameString;
outputInfo.innerText = "Create a class or choose a class from the left";
});
firestore.collection("Users").doc(id).collection("Classrooms").get().then(function(querySnapshot){
querySnapshot.forEach(function(doc){
classNameString = doc.id;
console.log(doc.id, " => ", doc.data());
$("li").append(''+doc.id+'<br/>');
});
});
}
The current testInfo function is as follows:
function testInfo(val){
console.log(val);
}
The following html code cannot work
'+doc.id+'
You are missing the double quotes, so the onclick is executed on the anchor element (the "#")
What you want to do is:
'+doc.id+'

TypeError on split()

I am trying to hide elements based on whether the user has added the class numbers to the database which I am retrieving through json data. If all the class numbers are present on the component I want to hide it.
At the moment I keep getting this error:
TypeError: $(...).data(...).split is not a function
export function VisaToggleComponent() {
let json = {
visa_subclass:[462,500,801]
};
let elements = document.querySelectorAll('[data-visa-hide]');
console.log(elements);
$(elements).each(function() {
let data = json.visa_subclass,
target = $(this).data('visa-hide').split(',').map(Number);
console.log(target);
for (let i in data) {
let val = data[i];
let index = target.indexOf(val);
if(index > -1) {
$(this).hide();
}
}
});
}
split is a method of the String object. Since you're getting
TypeError: $(...).data(...).split is not a function
It means $(this).data('visa-hide') is not a string.
To be honest, I didnt try to understand your code, however if you think $(this).data('visa-hide') is string-like data type you have to change $(this).data('visa-hide').split(',') to String.prototype.split.call($(this).data('visa-hide'), ',')

Add and count object in cookie javascript

I'm creating Add to cart module. I have Add to cart button, when the user click on it, then it will register JSON data of the item to cookie.
This is the example of the item object:
item =
{
DepartmentID :56,
CategoryID:117,
BrandID:19,
BrandImage:" ",
BrandName:"General",
Quantity:5,
ID:706
};
This is what I have done with cookie :
$('#addToCart').click(function(){
addObjToCookie('Cart',item);
});
function serializeObjToJSON(obj) {
var json = $.toJSON(obj);
return json;
}
function deserializeJSONToObj(json) {
var obj = $.evalJSON(json);
return obj;
}
function addObjToCookie(cookieName, obj) {
var jsonObj = serializeObjToJSON(obj);
$.cookie(cookieName, jsonObj);
}
function getDataFromCookie(cookieName){
var obj = deserializeJSONToObj($.cookie(cookieName));
return obj;
}
How can I append the item object into $(cookie('Cart')) when user click on Add to cart button, with this format:
[{"DepartmentID":56,"CategoryID":117,"BrandID":19,"BrandImage":" ","BrandName":"General","Quantity":5,"ID":706},
{"DepartmentID":56,"CategoryID":117,"BrandID":19,"BrandImage":" ","BrandName":"General","Quantity":1,"ID":707}];
How to count the item in Cart cookie, in this example the result is 2.
If the item in Cart is exist, then increase Quantity + 1.
Any help would be much appreciated, thank you.
Here are tweaks to answer 1 & 2
function addObjToCookie(cookieName, obj) {
// When adding see what's in there
var currentCart = getDataFromCookie( cookieName );
// Add what's new
currentCart.push( obj );
// Save new contents
$.cookie(cookieName, serializeObjToJSON( currentCart ) );
}
function getDataFromCookie(cookieName){
var val = $.cookie(cookieName);
// Make sure this returns something valid if it's not there
if ( !val ) {
return [];
}
// No need to save off something if you're not doing anything with it
return deserializeJSONToObj( val );
}
As for #3, before actually saving the new cookie content, loop through the return value til you find a match and if you do modify that rather than pushing to the array.
If you try the loop and it doesn't work, please post your attempt. I like to help but not to write code from scratch, so you can learn some too.

Categories

Resources