How can I add elements to arrays without overwriting them? - javascript

I have an issue with saving items into an array in JavaScript/Next.js.
At the beginning I have an empty array. Then a session is started, and I check if the session is empty or not. If it is empty, I write a response of a get-request into a variable. At the same time I also write the response of the get request into localstorage.
Basically I now want to write the value of localstorage into the array with the push-method.
In the next step my program should realize, that the session is not empty anymore and now the new value of the get-request should be stored into localstorage and at the same time it should be added as a new element of the variable. The old elements of the array should not be overwritten. I have now tried a couple of things, but I could not get it to work.
Does anybody have a hint for me, how to realize this problem? I would be very thankful, if anybody could help me on this one 😊
api.get('products?include=' + mainId, addOrViewCartConfig).then((response) => {
if (isEmpty(storedSession)) {
storeSession(response.data[0].id);
localStorage.setItem('ID', response.data[0].id);
var localCart = [];
};
if (!localCart.indexOf(parseInt(localStorage.getItem('ID')))) {
localCart.push(parseInt(localStorage.getItem('ID')));
} else {
alert('The item you are trying to add is already in your cart!');
return false;
}
viewCart();
}).catch((error) => {
console.log('apiError');
});

Related

Firebase Firestore: How to update or access and update a field value, in a map, in an array, in a document, that is in a collection

Sorry for the long title. Visually and more precise, I would like to update the stock value after a payment is made. However, I get stuck after querying the entire document (e.g. the selected one with title sneakers). Is there a way to actually query and update for example the Timberlands stock value to its value -1. Or do you have to get all data from the entire document. Then modify the desired part in javascript and update the entire document?
Here is a little snippet of a solution I came up with so far. However, this approach hurts my soul as it seems very inefficient.
const updateFirebaseStock = (orders) => {
orders.forEach( async (order) => {
try {
collRef = db.doc(`collections/${order.collectionid}`);
doc = await collRef.get();
data = doc.data();
//Here:const newItems = data.items.map(if it's corr name, update value, else just return object), results in desired new Array of objects.
//Then Update entire document by collRef.update({items: newItems})
} catch (error) {
console.error(error)
};
});
}
You don't need to get the document at all for that, all you have to do is use FieldValue.increment(), using your code as a starting point it could look like this:
collRef = db.doc(`collections/${order.collectionid}`);
collRef.update({
Price: firebase.firestore.FieldValue.increment(-1)
});
You can increment/decrement with any numeric value using that function.

how to save state of the page when refreshing? (HTML, JS)

(DISCLAIMER: I'm new to coding so my code probably isn't optimal. If you know a better way to do it, feel free to leave it in the comments )
Most of the time I had no idea what I was doing, but with patience and with you guys' help I came up with this:
if (window.localStorage) {
// Create the Key/Value
var cNum = localStorage.getItem("currentNumber");
if (localStorage.currentNumber == undefined) {
localStorage.setItem("currentNumber","0");}
// Variables
resetCount.innerHTML = localStorage.currentNumber;
// Functions
function btnR() {
cNum++;
localStorage.currentNumber = cNum;
resetCount.innerHTML = cNum;}}
else { console.log("No"); }
HTML:
<button id="resetButton" onclick="btnR()">Reset</button>
<p id="resetCount">0</p>
I was creating a button that each time you click on it, it reset the checkboxes, but I also wanted a counter to see how many times they got rested. The problem was that every time I click the button the counter also reset. Now that is solved I can try to apply the same thing for the checkboxes, so they don't reset on refresh either.
Note: I had to put the .SetItem in an if statement cause, even tho the value was in storage it kept setting back the value to zero every time I refreshed the page. This was the way I found to stop that.
You either need to set up a back end to send data to and save the information you want to keep stored, or save data in localStorage.
Just know it is not the best practice to save sensitive info in localStorage (as they can be compromised in cross-site scripting attacks).
localStorage.setItem puts a bit of data into localStorage (and that stays there till you clear it) and localStorage.getData extracts it.
This might help get you started on localStorage, but you will have to figure out the function to set the colour to the element you have.
let boxColour = localStorage.getItem("boxColour");
if (boxColour === null) {
setBoxColour("colour");
} else {
setBoxColour(boxColour);
}
function setBoxColour(colour){ localStorage.setItem("colour");}
/* Inside the function you have to get the item and change it's style attribute or add a class to add styles */
Careful with that localStorage data!
You could use LocalStorage.
It saves data in the page to be used after when the page is refreshed or closed and opened later.
Theres a example:
(Unfortunally, it seems to not work in the stackoverflow site, but if you try at your HTML file it will work)
var loadFunc = (elem) => {
console.log("Value saved is: "+ localStorage.getItem("savedValue"));
if(localStorage.getItem("savedValue")){ //checks if value is saved or not
elem.checked = localStorage.getItem("savedValue");
}
}
var clickFunc = (elem) => {
localStorage.setItem("savedValue", elem.checked); //set te value if in localStorage
}
Click the checkbox and the value will be saved.
<input type="checkbox" onload="loadFunc(this)" onclick="clickFunc(this)">

Refilling a form from a database

I'm so stuck on this I might not even be able to formulate a sensible question, but here goes...
I have a gigantic (and occasionally changing) form. I've found a reasonable way to get all the data from the form, turn it into an object, and save it to Firebase all at once. It looks like this, and is working fine (I think):
const incidentReport = document.getElementById('incident-report-form');
let irv = {};
// This works. All form data is saved to an object (as required by firebase), with the question as the name and the answer as the value.
incidentReport.addEventListener('submit', (e) => {
e.preventDefault();
[...incidentReport.elements].forEach((item) => {
let name = item.name;
let value = item.value;
irv = { ...irv, [name]: value };
});
// After all data is collected in one object, I send it to the database all at once.
db.collection('incident reports').add(irv);
});
Okay, so far so good... Now I want to get it back out of the database (I know how to do this) and repopulate the same form (no idea). I'm 100% stumped and I don't even know what to try.
Please forgive me if this is super easy and my brain is just shutting off... it's been a rough day.
Thanks in advance.
EDIT - This seems to work? I'm still very open to criticism and/or improvements.
// Get data from incident reports
//#TODO -> Need to create a list of incident reports, and then load the one //the user clicks on.
//Right now there is only one incident report in the database for testing.
db.collection('incident reports')
.get()
.then((snap) => {
snap.docs.forEach((element) => {
data = element.data(); //Previously declared but not included in this snippet, sorry.
});
for (let [key, value] of Object.entries(data)) {
let x = document.getElementsByName(key)[0];
if (x !== undefined) {
x.value = value;
}
}
});
If I understood it correctly, once you returned the data from your Firestore collection, you want to print them back in your HTML form. Considering that, it should not be very hard for you to achieve that.
Once you load the documents into an array, you should be able to assign the values to variables, that will be printed in the form. It should be something like this:
//Getting the collection and a specific document
var report = db.collection('incident reports').doc('<report>');
var getDoc = report.get()
.then(doc => {
if (!doc.exists) {
console.log('No such document!');
} else {
// Loading the values of the document into variables
var name = getDoc.data().name;
var value = getDoc.data().value;
...
// Other values loaded to other variables that you create
}
})
.catch(err => {
console.log('Error getting document', err);
});
Once you have loaded the values into variables, you just need to create a tag <script> that will be adding the values via Javascript into your HTML. Something that can look like this:
<script src="http://code.jquery.com/jquery-3.4.1.min.js"></script>
document.getElementById('<form item name>').innerHTML = name;
</script>
While this code is not tested, I believe it should be a good starting point for you, on what you need to do, to achieve your goal. It's only for one document, but since you are on tests right now and have only one document, you should be fine.
Besides that, you can find a good and full example on retrieving values from Firestore and priting in a page, in this other post here: How can I display all data from Firestore documents into html elements
Let me know if the information helped you!

Chaining multiple firebase actions and rollbacks

I'm using firebase and I want to chain some actions. Here is the scenario:
I want to add an item to the array and because I don't want to use push Id's I update a 'Last_Id' variable in firebase every time an item is added. I also update a 'Counter' variable to count the number of records (so I don't end up using numChildren() which can be slow).
The count and last_id variable are in the same tree like this:
Count:
---------->last_id
---------->Counter
I did this so that they can both be updated at the same time in a single transaction
So when I add an item I want 3 things to happen in order:
1- last_id is retreived
Item is added
last_id and Counter are
both updated
This is my code which makes use of promises.
add:function(ref,obj){
//get last_id
return baseRef.child('Count').child("Last_Id").once("value")
.then(function(snapshot){
return (snapshot.val()+1);
})
//add new data
.then(function(key){
return baseRef.child(ref).child(key).set(obj,function(error){
if (error)
console.log(error.code)
})
})
//update Count and last key
.then(this.updateCountAndKey(ref,1))
},
updateCountAndKey:function(ref,i){
return baseRef.child('Count').transaction(function(currentValue) {
if (currentValue!==null)
return {
Counter:(currentValue.Counter||0) +i,
Last_Id:(currentValue.Last_Id||0)+1
}
},function(err,commited,snap) {
if( commited )
console.log("updated counter to "+ snap.val());
else {
console.log("oh no"+err);
}
},false)
}
since I'm new to javascript and promises in particular want to know if this is a robust way of doing things. I also want to know how to do roll-backs if something goes wrong. so that if one thing fails then everything else fails (e.g if the update to Last_id and Counter fail then the item is not added).
Any help is much appreciated.
As the Firebase documentation specifies , transactions can only Atomically modify the data at this location, hence you can't use transactions to update other nodes in Firebase.
It is recommended to use push ID's (generated by Firebase in a safe way). This will remove the need to use a transaction for this part of your process. You will need to still use a transaction if you need to maintain the count. This should be done on success of #2 (adding an item).
Now your process will look like this:
push an item (auto generated ID)
on success, use a transaction to increment the count

Making an Array Variable Global in JavaScript

I'm setting a an array variable to 0 on load of my javascript.
var postArray= new Array();
However, I used this array to hold my objects that I retrieve from localStorage. It works when I upload more blog posts that get entered into localStorage and displays. However, after I refresh the page this is called again as is an empty array and say I go to enter my 3rd blog post after i've refreshed, my localStorage is set to only having the contents of my postArray. Therefore, I'm clearing out my localStorage when I dont want to.
if you throw it into an if statement, postArray is undefined.
if (localStorage.getItem("posts") === null) {
var postArray = new Array();
}
I'm trying to make the postArray global at the start yet only create a new array when localStorage is empty.
You should just get the content from the localStorage, and if it's empty, then return an empty array.
For example.
var postArray= getPosts();
function getPosts() {
var posts = localStorage.getItem("posts");
return posts ? JSON.parse(posts) : [];
}
i think you should use document coockie instead of array !!
when page is load read the cookie content if it's empty "localStorage" then store the "whatEver you want" value on its ! this is better than arrays

Categories

Resources